Включая файл python из корня проекта в сборку setup.py
Я пытаюсь включить файл python в каталог build/lib, созданный при запуске
python setup.py install
В частности, я хотел бы включить простой файл конфигурации ('definitions.py'), который определяет переменную ROOT_DIR, которая затем используется подпакетами. Файл Definition.py содержит:
import os
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
Моя цель состоит в том, чтобы файлы конфигурации в каждом подпакете ('config.py') вызывали ROOT_DIR для построения своих собственных абсолютных путей:
from definitions import ROOT_DIR
PACKAGE_DIR = os.path.join(ROOT_DIR, 'package1/')
Идея проистекает из этого ответа stackru: /questions/18953761/python-poluchit-put-k-kornevoj-strukture-proekta/18953780#18953780.
Однако этот файл "Definition.py" никогда не появляется в каталоге сборки при запуске "setup.py install".
Вот структура каталогов проекта:
проект | Setup── setup.py | Definition── definitions.py | Package── package1 | ├── __init__.py | Config── config.py | └── ... | Package── package2 | ├── __init__.py | └── ... └── ...
Мои многочисленные попытки не увенчались успехом (например, попытки, предложенные в /questions/5337544/kak-vklyuchit-staticheskie-fajlyi-v-setuptools-paket-python/5337581#5337581). Насколько я могу судить, это связано с тем, что defines.py находится на верхнем уровне структуры моего проекта (в котором отсутствует файл __init__.py).
Я пытался:
1)... используя переменную package-data в setuptools.setup()
package_data={'package': ['./definitions.py']}
но определение.py не отображается в сборке
(Я думаю, потому что defines.py отсутствует в "пакете", в котором есть __init__.py?).
2)... используя файл MANIFEST.in, но это также не работает
(Я думаю, потому что MANIFEST не работает с файлами.py?)
Мой вопрос:
Есть ли способ включить определения.py в каталог сборки?
Или есть ли лучший способ обеспечить доступ к абсолютным путям, созданным из каталога верхнего уровня для нескольких подпакетов?
1 ответ
Если вы ищете способ доступа к файлу данных, отличному от Python, в установленном модуле, как в вопросе, который вы связали (файл конфигурации в пакете верхнего уровня, который должен быть доступен в подпакетах), используйте pkg_resources
машины вместо того, чтобы придумывать собственное разрешение пути. Пример структуры проекта:
project
├── setup.py
└── root
├── __init__.py
├── config.txt
├── sub1
│ └── __init__.py
└── sub2
└── __init__.py
setup.py
:
from setuptools import setup
setup(
name='myproj',
...,
packages=['root', 'root.sub1', 'root.sub2'], # or setuptools.find_packages()
package_data={'root': ['config.txt']}
)
Обновить:
Как указал wim в комментариях, теперь есть бэкпорт для importlib.resources
(который доступен только в Python 3.7 и далее) - importlib_resources
, который предлагает современный ресурсный механизм, который использует pathlib
:
# access the filepath
importlib_resources.path('root', 'config.txt')
# access the contents as string
importlib_resources.read_text('root', 'config.txt')
# access the contents as file-like object
importlib_resources.open_binary('root', 'config.txt')
Оригинальный ответ
С помощью pkg_resources
Вы можете получить доступ к root/config.txt
из любой точки вашего пакета без необходимости выполнять какое-либо разрешение пути:
import pkg_resources
# access the filepath:
filepath = pkg_resources.resource_filename('root', 'config.txt')
# access the contents as string:
contents = pkg_resources.resource_string('root', 'config.txt')
# access the contents as file-like object:
contents = pkg_resources.resource_stream('root', 'config.txt')
и т.п.