Вопрос

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

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

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

Это было полезно?

Решение

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 - именно потому, что все происходит в одном и том же процессе!).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top