Включение файлов, отличных от Python, с помощью setup.py
Как мне сделать setup.py
включить файл, который не является частью кода? (В частности, это файл лицензии, но это может быть любая другая вещь.)
Я хочу иметь возможность управлять расположением файла. В исходной исходной папке файл находится в корневом каталоге. (то есть на том же уровне, что и самый верхний __init__.py
.) Я хочу, чтобы он оставался точно там, где установлен пакет, независимо от операционной системы. Как это сделать?
Ответы
Ответ 1
Вероятно, лучший способ сделать это - использовать директиву 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']}
Это dict
имен пакетов (empty = all packages) в список шаблонов (может включать в себя глобусы). Например, если вы хотите указывать только файлы внутри своего пакета, вы также можете это сделать:
package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}
Решение здесь, безусловно, не должно переименовывать ваши файлы не py
с расширением .py
.
Подробнее см. презентация Ian Bicking.
UPDATE: другой подход [лучше]
Другой подход, который хорошо работает, если вы просто хотите контролировать содержимое исходного дистрибутива (sdist
) и иметь файлы за пределами пакета (например, каталог верхнего уровня), заключается в добавлении файла MANIFEST.in
. См. документацию Python для формата этого файла.
С момента написания этого ответа я обнаружил, что использование MANIFEST.in
обычно менее расстраивает подход, чтобы убедиться, что ваш исходный дистрибутив (tar.gz
) имеет нужные вам файлы.
Например, если вы хотите включить requirements.txt
из верхнего уровня, рекурсивно включить каталог "данные" верхнего уровня:
include requirements.txt
recursive-include data *
Ответ 2
Чтобы выполнить то, что вы описываете, выполните два шага...
- Файл должен быть добавлен в исходный архив
- setup.py необходимо изменить, чтобы установить файл данных в исходный путь
Шаг 1: Чтобы добавить файл в исходный архив, включите его в MANIFEST
Создайте шаблон MANIFEST в папке, содержащей setup.py
MANIFEST - это в основном текстовый файл со списком всех файлов, которые будут включены в исходный архив.
Вот как выглядит MANIFEST для моего проекта:
- CHANGELOG.txt
- INSTALL.txt
- LICENSE.TXT
- pypreprocessor.py
- README.txt
- setup.py
- test.py
- todo.txt
Примечание. Хотя sdist делает автоматически добавляет файлы, я предпочитаю явно указывать их, а не предсказывая, что он делает и не делает.
Шаг 2. Чтобы установить файл данных в исходную папку, измените setup.py
Поскольку вы хотите добавить файл данных (LICENSE.txt) в папку установки источника, вам необходимо изменить путь установки данных, чтобы он соответствовал пути установки источника. Это необходимо, потому что по умолчанию файлы данных устанавливаются в другое место, кроме исходных файлов.
Чтобы изменить каталог установки данных в соответствии с исходной установкой dir...
Извлеките информацию об установочном каталоге из distutils с помощью:
from distutils.command.install import INSTALL_SCHEMES
Измените каталог установки данных в соответствии с исходным каталогом установки:
for scheme in INSTALL_SCHEMES.values():
scheme['data'] = scheme['purelib']
И добавьте файл данных и местоположение в setup():
data_files=[('', ['LICENSE.txt'])]
Примечание. Вышеупомянутые шаги должны выполнять именно то, что вы описали стандартным образом, не требуя каких-либо библиотек расширений.
Ответ 3
В setup.py при настройке (:
setup(
name = 'foo library'
...
package_data={
'foolibrary.folderA': ['*'], # All files from folder A
'foolibrary.folderB': ['*.txt'] #All text files from folder B
},
Ответ 4
Вот более простой ответ, который сработал у меня.
Во-первых, за комментарий 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']},
)
Ответ 5
Я просто хотел следить за тем, что я нашел, работая с Python 2.7 на Centos 6. Добавление пакетов_данных или data_files, как указано выше, не помогло мне. Я добавил MANIFEST.IN с файлами, которые я хотел, которые помещали файлы, отличные от python, в tarball, но не устанавливали их на целевой машине через RPM.
В конце концов, я смог получить файлы в своем решении, используя "параметры" в setup/setuptools. Файлы параметров позволяют изменять различные разделы файла spec из файла setup.py. Как следует.
from setuptools import setup
setup(
name='theProjectName',
version='1',
packages=['thePackage'],
url='',
license='',
author='me',
author_email='[email protected]',
description='',
options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)
file - 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
Ответ 6
создайте MANIFEST.in
в корне проекта с помощью recursive-include
в требуемый каталог или include
с именем файла.
include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *
документация можно найти здесь
Ответ 7
Выяснилось обходное решение: я переименовал my lgpl2.1_license.txt
в lgpl2.1_license.txt.py
и поместил несколько тройных цитат вокруг текста. Теперь мне не нужно использовать параметр data_files
или не указывать абсолютные пути. Я думаю, что сделать его модулем Python уродливо, но я считаю его менее уродливым, чем указание абсолютных путей.