Як включити дані пакета з 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.