Как ссылаться на относительные пути ресурсов при работе с репозиторием кода в Python


мы работаем с репозиторием кода, который развертывается как в Windows, так и в Linux - иногда в разных каталогах. Как один из модулей внутри проекта должен ссылаться на один из ресурсов, отличных от Python, в проекте (CSV-файлы и т. д.)?

Если мы сделаем что-то вроде:

thefile=open('test.csv')

или:

thefile=open('../somedirectory/test.csv')

он будет работать только тогда, когда скрипт запускается из одного конкретного каталога или подмножества каталогов.

что бы я хотел сделать это что-то вроде:

path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)

это правильный путь? Возможно ли это?

7 153

7 ответов:

попробуйте использовать имя файла относительно текущего пути файлов. Пример для './my_file':

fn = os.path.join(os.path.dirname(__file__), 'my_file')

Если вы используете инструменты настройки или распространения (a setup.py install) тогда "правильный" способ доступа к этим упакованным ресурсам, похоже, использует package_resources.

в вашем случае пример будет

import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")

который, конечно же, читает ресурс, а прочитанные двоичные данные будут значением my_data

Если вам просто нужно имя файла, вы также можете использовать

resource_filename(package_or_requirement, resource_name)

пример:

resource_filename("MyPackage","foo.dat")

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

см http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api

Я часто использую что-то вроде этого:

import os
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir'))

# if you have more paths to set, you might want to shorten this as
here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x))
DATA_DIR = here('datadir') 

pathjoin = os.path.join
# ...
# later in script
for fn in os.listdir(DATA_DIR):
    f = open(pathjoin(DATA_DIR, fn))
    # ...

переменная

__file__

содержит имя файла сценария, в котором вы пишете этот код, поэтому вы можете создавать пути относительно сценария, но все же писать с абсолютными путями. Он работает довольно хорошо по нескольким причинам:

  • путь абсолютный, но все же относительный
  • проект все еще может быть развернут в относительном контейнере

но вам нужно следить за платформой Совместимость - ОС Windows'.pathsep отличается от UNIX.

import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)

вы также пытаетесь нормализовать свой cwd С помощью os.path.abspath(os.getcwd()). Подробнее здесь.

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

использование абсолютного пути должно быть лучшим решением:

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')

Вы можете использовать построить в __file__ переменной. Он содержит путь к текущему файлу. Я бы реализовал getBaseOfProject в модуле в корне вашего проекта. Там я бы получил путь часть __file__ и вернул бы это. Затем этот метод можно использовать везде в вашем проекте.

Я потратил много времени, выясняя ответ на это, но я, наконец, получил его (и это на самом деле очень просто):

import sys
import os
sys.path.append(os.getcwd() + '/your/subfolder/of/choice')

# now import whatever other modules you want, both the standard ones,
# as the ones supplied in your subfolders

это добавит относительный путь вашей подпапки к каталогам для python, чтобы посмотреть Это довольно быстро и грязно, но это работает как шарм:)