Подставить каталог скрипта в строку

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

Нечто подобное работает нормально, если определено в том же файле, из которого вы его используете:

from os.path import abspath, dirname, join

def prepend_script_directory(s):
    here = dirname(abspath(__file__))
    return join(here, s)

Не желательно копировать, вставлять или переписывать эту же функцию в каждый модуль, но есть проблема: если вы переместите ее в отдельную библиотеку и импортируете как функцию, __file__ теперь ссылается на какой-то другой модуль, и результаты неверны.

Возможно, мы могли бы использовать это вместо этого, но кажется, что sys.argv также может быть ненадежным.

def prepend_script_directory(s):
    here = dirname(abspath(sys.argv[0]))
    return join(here, s)

Как написать prepend_script_directory надежно и правильно?

4 голоса | спросил wim 4 J000000Monday11 2011, 05:45:05

3 ответа


0

Лично я бы просто os.chdir в каталог скрипта всякий раз, когда я выполняю его. Это просто:

import os
os.chdir(os.path.split(__file__)[0])

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

prepend_script_directory(__file__, blah)

Если вы просто хотели написать

prepend_script_directory(blah)

вам придется делать специфичные для cpython трюки со стековыми фреймами:

import inspect

def getCallerModule():
    # gets globals of module called from, and prints out __file__ global
    print(inspect.currentframe().f_back.f_globals['__file__'])
ответил ninjagecko 4 J000000Monday11 2011, 05:57:45
0

Я думаю, причина, по которой это не пахнет, в том, что $PYTHONPATH (или sys.path) - это правильный общий механизм для использования.

ответил msw 4 J000000Monday11 2011, 05:57:41
0

Вы хотите pkg_resources

import pkg_resources
foo_fname = pkg_resources.resource_filename(__name__, "foo.txt")
ответил SingleNegationElimination 4 J000000Monday11 2011, 07:13:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132