Python: execfile из рабочего каталога другого файла? - PullRequest
7 голосов
/ 28 ноября 2009

У меня есть код, который загружает файл конфигурации по умолчанию, а затем позволяет пользователям предоставлять свои собственные файлы 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 Ответ

7 голосов
/ 28 ноября 2009

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

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

Редактировать : ОП говорит в комментарии, что 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 - именно потому, что все * происходит в одном и том же процессе!).

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

...