Як включити дані пакета з setuptools / distribute?


135

Під час використання setuptools / distribute я не можу змусити інсталятора витягнути будь-які 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/знаходиться файли даних.


2
У мене така ж проблема ... Проблема data_filesвирішена вручну . Але це схильне до помилок і не «відчуває мене правильно». Чи може хтось перевірити, що дійсно потрібно дублювати конфігурацію в обох package_dataі data_files?
ексгума

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буде працювати як для двійкових, так і для розподільних джерел.


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 контролює те, що згодом буде скопійовано у dir site_packages під час встановлення. Конфузно, що шляхи в MANIFEST.inвідносяться до місця установки root.py та package_dataвідносяться до кореня окремих пакетів (наприклад, модулів).
Едвард Ньюелл

9
"Змінено у версії 2.7. Усі файли, які відповідають_пакетним даним, будуть додані до файлу 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ключове слово.

Витягнувши цей аргумент, виправили його, і це випадково, чому він також працював, коли ви перейшли на дистрибутив, оскільки він не приймає цей аргумент.


2
Мій досвід відрізняється, у мене була та сама проблема, не включаючи include_package_data=Trueзапис. Єдине рішення для мене - додати запис у Manifest, як було запропоновано вище. Зауважте, я використовував setuptools, можливо, ваша версія працює з "дистрибутивом"?
TimStaley

4
Фактична причина усунення include_package_dataпроблеми вирішується далі в оригінальному тексті - Якщо використовується специфічний для include_package_dataаргументу setuptools , вказані файли 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.


16

include_package_data=True працював на мене.

Якщо ви використовуєте git, не забудьте включити setuptools-gitв install_requires. Набагато менше нудно, ніж мати Manifestабо включати весь шлях package_data(у моєму випадку це програма джанго з усіма видами статики)

(вставив коментар, який я зробив, оскільки 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'],
   },
)

2
розповсюдження не застаріло, воно замінює distutils. Я не знаю, чому у вас виникли проблеми, але це не причина.
agf

1
Такою була відповідь, яку я отримав від IRC, тому кому я вірю? Якщо у вас є робочий приклад використання дистрибутиву, я вдячний тоді.
cmcginty

6
уточнення: розподіл призначений для заміни setuptools, обидва побудовані поверх distutils. Сам distutils врешті-решт буде замінений новим пакетом, який називається "distutils2" у python2 та "упаковкою" у python3
Кевін Хорн

1
Перехід на дистрибутив вирішив мою проблему, коли include_package_data=Trueїї не дотримувались . Тож для цього налаштування вам потрібен лише MANIFEST.in - не потрібно дублювати список файлів у package_dataналаштуваннях.
Даніель Соколовський

4

Стародавнє питання, і все ж ... управління пакетами python дійсно залишає бажати кращого. Тож у мене був випадок використання установки локально за допомогою pip у вказаному каталозі, і я був здивований, і шлях_пакет_даних та даних_філів не вийшли. Я не хотів додавати ще один файл до репо, тому я в кінцевому рахунку використовував 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'],
   },
)

Повна інша відповідь stackoverflow тут


Спробував це, але все одно нічого не копіюється.
Герріт

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 та колеса, щоб відповісти на це. Це працювало для мене, використовуючи pip install.
Герріт

Це тому pip install, що для досить сучасних версій pip спочатку побудують колесо, а потім встановлять це. Однак для багатьох користувачів такий підхід мовчки не зможе включити дані пакета. Детальну інформацію про це див. У прийнятій відповіді та коментарях під нею. Використання A setup.cfg- це справді інший спосіб написання того, що вже робив ОП setup.pyу запитанні (передаючи package_dataаргумент ключового слова в дзвінку до setup), тому я не думаю, що це особливо корисно як відповідь на це питання . Це взагалі не вирішення основної проблеми.
Вім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.