2009-06-18 3 views
12

Как ссылаться на файл относительно каталога пакета?Относительные пути к файлам в пакетах Python

Моя структура каталогов:

 
    /foo 
    package1/ 
     resources/ 
     __init__.py 
    package2/ 
     resources/ 
     __init__.py 
    script.py 

script.py импортирует пакеты package1 и package2. Хотя пакеты могут быть импортированы любым другим скриптом в системе. Как я должен ссылаться на ресурсы внутри, скажем, package1, чтобы убедиться, что он будет работать в случае, если os.path.curdir является произвольным?

ответ

14

Если вы хотите ссылаться на файлы из папки foo/package1/resources, вы хотели бы использовать переменную __file__ модуля. Внутри foo/package1/__init__.py:

from os import path 
resources_dir = path.join(path.dirname(__file__), 'resources') 
+0

Как отметил другой ответ, это не сработает, если ваше приложение упаковано в zip-файл. – Glyph

0

Это плохая идея, потому что, если ваш пакет был установлен как его сжатым яйцо, то ресурсы могут быть недоступны.

Если вы используете setuptool, не забудьте добавить zip_safe = False в конфигурацию setup.py.

+3

Это правда, но это должно было быть скорее в комментарии, чем в ответе, поскольку он не отвечает на вопрос. – Glyph

4

Вы можете быть 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.

4

Простой/безопасный способ сделать это с помощью метода 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') 

Это дает вам чистое решение, которое также (если я не ошибаюсь).

Смежные вопросы