Относительные пути к файлам в пакетах Python
Как ссылаться на файл относительно каталога пакета?
Моя структура каталогов:
/foo
package1/
resources/
__init__.py
package2/
resources/
__init__.py
script.py
script.py
импортирует пакеты package1
и package2
. Хотя пакеты могут быть импортированы любым другим script в системе. Как я должен ссылаться на ресурсы внутри, скажем, package1
, чтобы убедиться, что он будет работать в случае, если os.path.curdir
является произвольным?
Ответы
Ответ 1
Если вы хотите ссылаться на файлы из папки foo/package1/resources
, вы хотели бы использовать переменную __file__
модуля. Внутри foo/package1/__init__.py
:
from os import path
resources_dir = path.join(path.dirname(__file__), 'resources')
Ответ 2
Вы можете быть zip-safe и в то же время использовать удобный удобный API, если вы используете twisted.python.modules.
Например, если у меня есть data.txt
с некоторым текстом в нем, а этот sample.py
в одном каталоге:
from twisted.python.modules import getModule
moduleDirectory = getModule(__name__).filePath.parent()
print repr(moduleDirectory.child("data.txt").open().read())
тогда импорт sample
сделает следующее:
>>> import sample
'Hello, data!\n'
>>>
Если ваш модуль находится в обычном каталоге, getModule(__name__).filePath
будет FilePath; если он находится в zip файле, он будет ZipPath, который поддерживает большинство, но не всех, тех же API.
Ответ 3
Простой/безопасный способ сделать это - использовать метод resource_filename
из pkg_resources (который распространяется с setuptools):
from pkg_resources import resource_filename
filepath = resource_filename('package1', 'resources/thefile')
Или, если вы реализуете это внутри package1/___init___.py
:
from pkg_resources import resource_filename
filepath = resource_filename(__name__, 'resources/thefile')
Это дает вам чистое решение, которое также (если я не ошибаюсь) безопасно для zip.
Ответ 4
Это плохая идея, потому что если ваш пакет был установлен как заархивированное яйцо, тогда ресурсы могут быть недоступны.
Если вы используете setuptool, не забудьте добавить zip_safe = False в конфигурацию setup.py.