Python: execfile из рабочего каталога другого файла?
-
06-07-2019 - |
Вопрос
У меня есть некоторый код, который загружает файл конфигурации по умолчанию, а затем позволяет пользователям предоставлять свои собственные файлы 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
- именно потому, что все происходит в одном и том же процессе!).
Итак, любые проблемы, которые ОП продолжает наблюдать, не привязаны к текущему рабочему каталогу (трудно определить, какими они могут быть на самом деле, не видя код и точные детали обнаруженных проблем). ; -.) р>