Включая не-Python файлы с setup.py - PullRequest
160 голосов
/ 23 октября 2009

Как мне сделать setup.py включением файла, который не является частью кода? (В частности, это файл лицензии, но это может быть любая другая вещь.)

Я хочу иметь возможность контролировать местоположение файла. В исходной исходной папке файл находится в корне пакета. (то есть на том же уровне, что и самый верхний __init__.py.) Я хочу, чтобы он оставался там точно при установке пакета, независимо от операционной системы. Как мне это сделать?

Ответы [ 9 ]

167 голосов
/ 07 декабря 2009

Вероятно, лучший способ сделать это - использовать директиву setuptools package_data. Это означает использование setuptools (или distribute) вместо distutils, но это очень плавное «обновление».

Вот полный (но не проверенный) пример:

from setuptools import setup, find_packages

setup(
    name='your_project_name',
    version='0.1',
    description='A description.',
    packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']),
    package_data={'': ['license.txt']},
    include_package_data=True,
    install_requires=[],
)

Обратите внимание на конкретные строки, которые здесь важны:

package_data={'': ['license.txt']},
include_package_data=True,

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

package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}

Решением здесь, безусловно, является , а не для переименования файлов, не являющихся py, с расширением .py.

См. презентацию Иана Бикинга для получения дополнительной информации.

ОБНОВЛЕНИЕ: еще один [лучший] подход

Другой подход, который работает хорошо, если вы просто хотите контролировать содержимое исходного дистрибутива (sdist) и иметь файлы вне пакета (например, каталог верхнего уровня), - это добавить файл MANIFEST.in. Информацию о формате этого файла см. В документации по Python .

С момента написания этого ответа я обнаружил, что использование MANIFEST.in обычно является менее разочаровывающим подходом, чтобы просто убедиться, что в исходном дистрибутиве (tar.gz) есть нужные вам файлы.

Например, если вы хотите включить requirements.txt из верхнего уровня, рекурсивно включите каталог «data» верхнего уровня:

include requirements.txt
recursive-include data *

Тем не менее, для того, чтобы эти файлы были скопированы во время установки в папку пакета внутри site-пакетов, вам необходимо указать include_package_data=True для функции setup(). См. Добавление файлов без кода для получения дополнительной информации.

43 голосов
/ 15 июня 2010

Чтобы выполнить то, что вы описываете, потребуется два шага ...

  • Файл должен быть добавлен в исходный архив
  • setup.py необходимо изменить, чтобы установить файл данных в исходный путь

Шаг 1: Чтобы добавить файл в архив с исходным кодом, включите его в МАНИФЕСТ

Создайте шаблон MANIFEST в папке, содержащей setup.py

MANIFEST - это, по сути, текстовый файл со списком всех файлов, которые будут включены в исходный архив.

Вот как выглядит МАНИФЕСТ для моего проекта:

  • CHANGELOG.txt
  • INSTALL.txt
  • LICENSE.TXT
  • pypreprocessor.py
  • README.txt
  • setup.py
  • test.py
  • todo.txt

Примечание. Хотя sdist действительно добавляет некоторые файлы автоматически , я предпочитаю явно указывать их, чтобы быть уверенным, вместо того, чтобы предсказывать, что он делает, а что нет. *

Шаг 2. Чтобы установить файл данных в исходную папку, измените файл setup.py

Поскольку вы хотите добавить файл данных (LICENSE.txt) в исходную папку установки, вам нужно изменить путь установки данных, чтобы он соответствовал пути установки источника. Это необходимо, поскольку по умолчанию файлы данных устанавливаются в другое место, чем исходные файлы.

Чтобы изменить каталог установки данных в соответствии с каталогом установки источника ...

Получите информацию установочного каталога из distutils с помощью:

from distutils.command.install import INSTALL_SCHEMES

Измените каталог установки данных в соответствии с каталогом установки источника:

for scheme in INSTALL_SCHEMES.values():
    scheme['data'] = scheme['purelib']

И добавьте файл данных и расположение в setup ():

data_files=[('', ['LICENSE.txt'])]

Примечание. Приведенные выше действия должны выполнять в точности то, что вы описали стандартным способом, без каких-либо библиотек расширений.

11 голосов
/ 20 сентября 2017

создать MANIFEST.in в корне проекта с recursive-include в нужном каталоге или include с именем файла.

include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *

документацию можно найти здесь

5 голосов
/ 27 декабря 2014

В setup.py в настройках (:

setup(
   name = 'foo library'
   ...
  package_data={
   'foolibrary.folderA': ['*'],     # All files from folder A
   'foolibrary.folderB': ['*.txt']  #All text files from folder B
   },
3 голосов
/ 27 октября 2018

Шаг 1: создайте файл MANIFEST.in в той же папке с setup.py

Шаг 2: укажите относительный путь к файлам, которые вы хотите добавить в MANIFEST.in

include README.rst
include docs/*.txt
include funniest/data.json

Шаг 3: установите include_package_data=True в функции setup(), чтобы скопировать эти файлы в пакет сайта

ссылка здесь

3 голосов
/ 06 августа 2013

Вот более простой ответ, который работал для меня.

Во-первых, согласно комментарию Python Dev выше, setuptools не требуется:

package_data is also available to pure distutils setup scripts 
since 2.3. – Éric Araujo

Это замечательно, потому что наложение требования setuptools на ваш пакет означает, что вам также придется установить его. Короче говоря:

from distutils.core import setup

setup(
    # ...snip...
    packages          = ['pkgname'],
    package_data      = {'pkgname': ['license.txt']},
)
1 голос
/ 28 сентября 2018

Я хотел оставить комментарий к одному из вопросов, но у меня недостаточно репутации, чтобы сделать это>.>

Вот что сработало для меня (придумал это после обращения к документации):

package_data={
    'mypkg': ['../*.txt']
},

include_package_data: False

Последняя строка была, как ни странно, также крайне важна для меня (вы также можете опустить этот аргумент ключевого слова - он работает так же).

Это копирует все текстовые файлы в вашем верхнем или корневом каталоге (на один уровень выше от пакета mypkg, который вы хотите распространить).

Надеюсь, это поможет!

1 голос
/ 01 июня 2015

Я просто хотел продолжить, что я нашел, работая с Python 2.7 на Centos 6. Добавление package_data или data_files, как упомянуто выше, не работает для меня. Я добавил MANIFEST.IN с нужными мне файлами, которые помещают файлы, отличные от python, в tarball, но не устанавливал их на целевой машине через RPM.

В итоге я смог получить файлы в своем решении, используя «опции» в setup / setuptools. Файлы опций позволяют вам изменять различные разделы файла спецификации из setup.py. Следующим образом.

from setuptools import setup


setup(
    name='theProjectName',
    version='1',
    packages=['thePackage'],
    url='',
    license='',
    author='me',
    author_email='me@email.com',
    description='',
    options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)

файл - MANIFEST.in:

include license.txt

file - filewithinstallcommands:

mkdir -p $RPM_BUILD_ROOT/pathtoinstall/
#this line installs your python files
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
#install license.txt into /pathtoinstall folder
install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/
echo /pathtoinstall/license.txt >> INSTALLED_FILES
0 голосов
/ 23 октября 2009

Обдумал обходной путь: я переименовал свой lgpl2.1_license.txt в lgpl2.1_license.txt.py и поместил несколько тройных кавычек вокруг текста. Теперь мне не нужно ни использовать параметр data_files, ни указывать абсолютные пути. Я знаю, что делать его модулем Python некрасиво, но считаю его менее уродливым, чем указание абсолютных путей.

...