Включая файлы, отличные от Python, с setup.py
Вопрос
Как мне сделать setup.py
включить файл, который не является частью кода?(В частности, это файл лицензии, но это может быть любая другая вещь.)
Я хочу иметь возможность контролировать расположение файла.В исходной папке файл находится в корневом каталоге пакета.(т.е.на том же уровне, что и самый верхний __init__.py
.) Я хочу, чтобы он оставался точно таким же, когда пакет установлен, независимо от операционной системы.Как мне это сделать?
Решение
Вероятно, лучший способ сделать это - использовать 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-packages, вам необходимо предоставить include_package_data=True
к тому setup()
функция.Видишь Добавление файлов, не содержащих код для получения дополнительной информации.
Другие советы
Чтобы выполнить то, что вы описываете, потребуется два шага...
- Файл необходимо добавить в исходный архив архива
- setup.py необходимо внести изменения, чтобы установить файл данных по исходному пути
Шаг 1:Чтобы добавить файл в исходный архив, включите его в МАНИФЕСТ
Создать ПРОЯВЛЯЮЩИЙСЯ шаблон в папке, содержащей setup.py
МАНИФЕСТ - это, по сути, текстовый файл со списком всех файлов, которые будут включены в исходный архив.
Вот как выглядит МАНИФЕСТ для моего проекта:
- 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'])]
Примечание:Описанные выше шаги должны выполнять именно то, что вы описали стандартным образом, не требуя каких-либо библиотек расширений.
создайте MANIFEST.in
в корневом каталоге проекта с помощью recursive-include
в нужном каталоге или include
с именем файла.
include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *
В setup.py в настройках (:
setup(
name = 'foo library'
...
package_data={
'foolibrary.folderA': ['*'], # All files from folder A
'foolibrary.folderB': ['*.txt'] #All text files from folder B
},
Вот более простой ответ, который сработал для меня. Р>
Во-первых, согласно приведенному выше комментарию 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: создайте файл MANIFEST.in
в той же папке, что и файл setup.py
Шаг 2: укажите относительный путь к файлам, которые вы хотите добавить в MANIFEST.in
include README.rst
include docs/*.txt
include funniest/data.json
Шаг 3: установите include_package_data = True
в функции setup ()
, чтобы скопировать эти файлы в пакет сайта
Я просто хотел продолжить работу с Python 2.7 в Centos 6. Добавление пакетов_данных или файлов_данных, как упомянуто выше, не сработало для меня. Я добавил MANIFEST.IN с нужными мне файлами, которые помещают файлы, отличные от python, в tarball, но не устанавливал их на целевой машине через RPM. Р>
В итоге я смог получить файлы в своем решении, используя " параметры " в настройках / 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
файл - файл с командами установки:
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
Я хотел оставить комментарий к одному из вопросов, но у меня недостаточно репутации, чтобы сделать это >.>
Вот что сработало у меня (придумал это после обращения к документам):
package_data={
'mypkg': ['../*.txt']
},
include_package_data: False
Последняя строка, как ни странно, также оказалась для меня решающей (вы также можете опустить этот аргумент ключевого слова - он работает так же).
Что это делает, так это копирует все текстовые файлы в ваш каталог верхнего уровня или корневой каталог (на один уровень выше пакета mypkg
вы хотите распространять).
Надеюсь, это поможет!
Обошел обходной путь: я переименовал свой lgpl2.1_license.txt
в lgpl2.1_license.txt.py
и поместил несколько тройных кавычек вокруг текста. Теперь мне не нужно ни использовать параметр data_files
, ни указывать абсолютные пути. Я знаю, что сделать его модулем Python некрасиво, но считаю его менее уродливым, чем указание абсолютных путей.