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 все еще наблюдает, не привязаны к текущему рабочему каталогу (трудно определить, какими они могут быть на самом деле, не видя код и точные детали обнаруженных проблем;-).