Python: execfile из рабочего каталога другого файла?

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

# foo.py

def load(cfg_path=None):
    # load default configuration
    exec(default_config)

    # load user-specific configuration
    if cfg_path:
        execfile(cfg_path)

Однако есть проблема: execfile() выполняет директивы в файле, указанном cfg_path как будто это было в рабочем каталоге foo.py, а не собственный рабочий каталог. Таким образом, import директивы могут потерпеть неудачу, если cfg_path Файл, скажем, from m import x где m это модуль в том же каталоге, что и cfg_path,

Как я execfile() из рабочего каталога своего аргумента или иным образом добиться эквивалентного результата? Кроме того, мне сказали, что execfile устарел в Python 3 и что я должен использовать execТак что, если есть лучший способ, которым я должен это делать, я весь в ушах.

Примечание: я не думаю, что решения, которые просто меняют рабочий каталог, являются правильными. Насколько я могу судить, эти модули не будут помещены в путь поиска модулей интерпретатора.

1 ответ

Решение

os.chdir позволяет вам изменить рабочий каталог по вашему желанию (вы можете извлечь рабочий каталог из cfg_path с os.path.dirname); Обязательно сначала получите текущий каталог с помощью os.getcwd, если вы хотите восстановить его, когда закончите работу cfg_path,

Python 3 действительно удаляет execfile (в пользу последовательности, в которой вы читаете файл, compile содержание, то exec их), но вам не нужно беспокоиться об этом, если вы в настоящее время программируете на Python 2.6, так как перевод с 2 на 3 переводит все это плавно и без проблем.

Изменить: ОП говорит, в комментарии, что execfile запускает отдельный процесс и не уважает текущий рабочий каталог. Это неверно, и вот пример, показывающий, что это так:

import os

def makeascript(where):
  f = open(where, 'w')
  f.write('import os\nprint "Dir in file:", os.getcwd()\n')
  f.close()

def main():
  where = '/tmp/bah.py'
  makeascript(where)
  execfile(where)
  os.chdir('/tmp')
  execfile(where)

if __name__ == '__main__':
  main()

Запуск этого на моей машине производит вывод, такой как:

Dir in file: /Users/aleax/stko
Dir in file: /private/tmp

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

Таким образом, любые проблемы, которые OP все еще наблюдает, не привязаны к текущему рабочему каталогу (трудно определить, какими они могут быть на самом деле, не видя код и точные детали обнаруженных проблем;-).

Другие вопросы по тегам