Как включить данные пакета в setuptools / distribue?

136

При использовании setuptools / распространять, я не могу заставить установщик вытянуть какие-либо package_dataфайлы. Все, что я прочитал, говорит о том, что следующий способ является правильным. Может кто-нибудь, пожалуйста, посоветуйте?

setup(
   name='myapp',
   packages=find_packages(),
   package_data={
      'myapp': ['data/*.txt'],
   },
   include_package_data=True,
   zip_safe=False,
   install_requires=['distribute'],
)

где myapp/data/расположение файлов данных.

cmcginty
источник
2
У меня та же проблема ... Указание вручную data_filesрешило проблему. Но это подвержено ошибкам и не "чувствует себя хорошо" для меня. Может кто - то проверить , что это действительно необходимо дублировать конфигурацию в обоих package_dataи data_files?
exhuma
github.com/wimglenn/resources-example Показывает современную структуру проекта setuptools, которая может правильно упаковать файлы данных в колеса и sdists, используя pyproject.toml. Нет setup.pyне требуется файл.
Вим

Ответы:

289

Я понимаю, что это старый вопрос, но для людей, которые находят свой путь через Google: package_dataэто грязная ложь . Он используется только при сборке бинарных пакетов ( python setup.py bdist ...), но не при сборке пакетов с исходным кодом ( python setup.py sdist ...). Это, конечно, смешно - можно было бы ожидать, что создание исходного дистрибутива приведет к коллекции файлов, которые могут быть отправлены кому-то еще для создания бинарного дистрибутива.

В любом случае, использование MANIFEST.inбудет работать как для двоичного, так и для исходного дистрибутива.

larsks
источник
97
Я исследовал эту проблему в течение последнего часа и пробовал много подходов. Как вы говорите, package_dataработает bdistи нет sdist. Тем не менее , MANIFEST.inработает для sdist, но не для bdist! Поэтому лучшее, что я смог придумать, - это включить и то, package_dataи другое MANIFEST.in, чтобы учесть и то, bdistи другое sdist.
Уэсли Боуг
7
Я нашел другой, чтобы поддержать @WesleyBaugh. В stackoverflow.com/a/2969087/261718 , используйте MANIFEST.inдля файлов, которые вы не будете устанавливать, например, package_dataдля документации, и для файлов, которые вы используете, которые не являются кодом Python (например, изображение или шаблон).
Дрейк Гуань
12
Я использую sdist, и должен был включить оба MANIFEST.in и package_data . Кажется, что он MANIFEST.inконтролирует то, что входит в дистрибутив, а package_data контролирует то, что впоследствии копируется в каталог site_packages во время установки. Путаница в путях MANIFEST.inотносительно расположения setup.py и package_dataотносительно корня отдельных пакетов (например, модулей).
Эдвард Ньюэлл
9
«Изменено в версии 2.7: Все файлы, соответствующие package_data, будут добавлены в файл MANIFEST, если шаблон не указан. См. Определение файлов для распространения». от distutils . Таким образом, вы увидите, как файлы package_dataавтоматически включаются в ZIP- архив , только если у вас нет файла MANIFEST.in , и только если вы используете версию 2.7+.
Джонус
29
Серьезно, я чувствую, что этот билет является сеансом групповой терапии для людей, использующих setuptools и выясняющих, какое ужасное место они нашли в жизни.
Мэтт Джойс
32

У меня была такая же проблема. Решение было просто удалить include_package_data=True.

После прочтения здесь , я понял , что include_package_dataцели включать файлы из контроля версий , а не просто «включает в себя данные пакета» , как следует из названия. Из документов:

Файлы данных [of include_package_data] должны находиться под контролем CVS или Subversion

...

Если вы хотите более детальный контроль над тем, какие файлы включены (например, если у вас есть файлы документации в ваших каталогах пакетов и вы хотите исключить их из установки), вы также можете использовать package_dataключевое слово.

Устранение этого аргумента исправило его, что, по совпадению, также сработало, когда вы переключились на distutils, поскольку он не принимает этот аргумент.

Джо
источник
2
Мой опыт отличается, у меня была такая же проблема без включения include_package_data=Trueзаписи. Единственное решение для меня - добавить запись в манифест, как предложено выше. Имейте в виду, я использовал setuptools, может быть, ваша версия работает с «распространять»?
TimStaley
4
Реальная причина , почему удаление include_package_dataпроблемы решает далее в оригинальном тексте - При использовании Setuptools специфичного include_package_dataаргумента, файлы , указанные package_dataне будет автоматически добавлены к манифесту , если они не указаны в MANIFEST.inфайле.
Петр Доброгост
Каков случай использования package_dataустановки непустого списка и указания include_package_data=False? И зачем вам нужно указывать файлы дважды в MANIFEST.inи package_data?
Герберт
21

Следование рекомендации @Joe по удалению include_package_data=Trueстроки также сработало для меня.

Чтобы уточнить немного, у меня нет MANIFEST.in файла. Я использую Git, а не CVS.

Репозиторий принимает такую ​​форму:

/myrepo
    - .git/
    - setup.py
    - myproject
        - __init__.py
        - some_mod
            - __init__.py
            - animals.py
            - rocks.py
        - config
            - __init__.py
            - settings.py
            - other_settings.special
            - cool.huh
            - other_settings.xml
        - words
            - __init__.py
            word_set.txt

setup.py:

from setuptools import setup, find_packages
import os.path

setup (
    name='myproject',
    version = "4.19",
    packages = find_packages(),  
    # package_dir={'mypkg': 'src/mypkg'},  # didnt use this.
    package_data = {
        # If any package contains *.txt or *.rst files, include them:
        '': ['*.txt', '*.xml', '*.special', '*.huh'],
    },

#
    # Oddly enough, include_package_data=True prevented package_data from working.
    # include_package_data=True, # Commented out.
    data_files=[
#               ('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
        ('/opt/local/myproject/etc', ['myproject/config/settings.py', 'myproject/config/other_settings.special']),
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'cool.huh')]),
#
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'other_settings.xml')]),
        ('/opt/local/myproject/data', [os.path.join('myproject/words', 'word_set.txt')]),
    ],

    install_requires=[ 'jsonschema',
        'logging', ],

     entry_points = {
        'console_scripts': [
            # Blah...
        ], },
)

Я бегу python setup.py sdistза исходным дистрибутивом (не пробовал бинарный).

И когда внутри совершенно новой виртуальной среды, у меня есть myproject-4.19.tar.gz, файл, и я использую

(venv) pip install ~/myproject-4.19.tar.gz
...

И помимо всего того, что устанавливается в моей виртуальной среде site-packages, эти специальные файлы данных устанавливаются в /opt/local/myproject/dataи /opt/local/myproject/etc.

HeyWatchThis
источник
16

include_package_data=True работал на меня.

Если вы используете git, не забудьте включить setuptools-gitв install_requires. Намного менее скучно, чем наличие Manifestили включение всего пути package_data(в моем случае это приложение django со всеми видами статики)

(вставил комментарий, который я сделал, поскольку k3-rnc упомянул, что это действительно полезно как есть)

Винсент
источник
7

Обновление : этот ответ старый и информация больше не действительна. Все конфиги setup.py должны использовать import setuptools. Я добавил более полный ответ на https://stackoverflow.com/a/49501350/64313


Я решил это, переключившись на distutils. Похоже, дистрибутив устарел и / или не работает.

from distutils.core import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_data={
      'myapp': ['data/*.txt'],
   },
)
cmcginty
источник
2
Распространение не считается устаревшим, оно заменяет distutils. Я не знаю, почему у вас возникла проблема, но это не причина.
agf
1
Это был ответ от IRC, так кому я верю? Если у вас есть рабочий пример использования дистрибутива, я был бы признателен.
cmcginty
6
Пояснение: дистрибутив предназначен для замены setuptools, оба построены поверх distutils. Сам по себе distutils будет в конечном итоге заменен новым пакетом, названным «distutils2» в python2 и «package» в python3
Кевин Хорн
1
Переключение на distutils решило мою проблему, где include_package_data=Trueне было чести. Таким образом, с этим параметром вам нужен только MANIFEST.in - не нужно дублировать список файлов в package_dataнастройке.
Даниэль Соколовский
4

Древний вопрос и все же ... пакетное управление python действительно оставляет желать лучшего. Поэтому у меня был сценарий использования установки pip локально в указанный каталог, и я был удивлен, что пути package_data и data_files не сработали. Я не был заинтересован в добавлении еще одного файла в репозиторий, поэтому в итоге я использовал data_files и параметр setup.py --install-data; что-то вроде этого

pip install . --install-option="--install-data=$PWD/package" -t package  
Мэт Бейкер
источник
3

У меня была такая же проблема в течение нескольких дней, но даже эта ветка не смогла мне помочь, потому что все сбивало с толку. Поэтому я провел исследование и нашел следующее решение:

В основном в этом случае вы должны сделать:

from setuptools import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_dir={'myapp':'myapp'}, # the one line where all the magic happens
   package_data={
      'myapp': ['data/*.txt'],
   },
)

Полный другой ответ на стеке здесь

moctarjallo
источник
Пробовал это, но все равно ничего не копируется.
Gerrit
3

Просто удалите строку:

include_package_data=True,

из вашего скрипта установки, и он будет работать нормально. (Протестировано только сейчас с последними установочными инструментами.)

Ян
источник
Это безумие, но оно работает и с, sdistи bdist_wheelты проверил почему?
Сабольч
1
Я действительно могу подтвердить, что sdistигнорирует, package_dataкогда это установлено.
Сандер Штеффанн
В этот момент прошли месяцы, но я, кажется, вспомнил, как копался в коде, дважды терялся, брал ОЧЕНЬ тонкую гребенку в документацию и получал удовлетворение. По-видимому, различные примеры сценариев содержат этот флаг, и это не вызывает головной боли.
Ян
1

Использование setup.cfg (setuptools ≥ 30.3.0)

Начиная с setuptools 30.3.0 (выпущен 2016-12-08), вы можете сохранить setup.pyочень маленький размер и перенести конфигурацию в setup.cfgфайл. При таком подходе вы можете поместить данные вашего пакета в [options.package_data]раздел:

[options.package_data]
* = *.txt, *.rst
hello = *.msg

В этом случае ваш setup.pyможет быть коротким как:

from setuptools import setup
setup()

Для получения дополнительной информации см. Настройка настройки с использованием файлов setup.cfg .

Есть некоторые разговоры об осужденииsetup.cfg в пользу того, pyproject.tomlчто предложено в PEP 518 , но это все еще временно на 2020-02-21.

Геррит
источник
В этом ответе не упоминается файл MANIFEST, поэтому я думаю, что он не будет работать с sdists. Только с колесами. Вы должны упомянуть это.
Вим
@ wim У меня недостаточно понимания MANIFEST, sdist и wheel, чтобы ответить на это. Это сработало для меня, используя pip install.
Геррит
Это потому pip install, что для достаточно современных версий pip сначала нужно создать колесо, а затем установить его. Тем не менее, для многих пользователей этот подход не будет включать данные пакета. См. Принятый ответ и комментарии под ним для подробностей об этом. На setup.cfgсамом деле использование a - это просто другой способ записать, что ОП уже делал в setup.pyвопросе (передавая package_dataаргумент ключевого слова в вызове setup), поэтому я не думаю, что это особенно полезно в качестве ответа на этот вопрос . Это не решение основной проблемы вообще.
Вим