2009-11-28 4 views
7

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

# 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, поэтому, если есть лучший способ, которым я должен это делать, я все уши.

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

ответ

7

os.chdir позволяет вам изменить рабочий каталог по своему усмотрению (вы можете извлечь рабочий каталог cfg_path с помощью os.path.dirname); не забудьте сначала получить текущий каталог с os.getcwd, если вы хотите восстановить его, когда закончите exec'ing 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 - именно потому, что все - это, происходящее в том же процессе!).

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

+0

Спасибо за ваш ответ. К сожалению, это не работает для меня. 'execfile()', похоже, запускает совершенно новый процесс с собственным рабочим каталогом, который не совпадает с тем, с которого я запускаю. –

+0

Нет, @Kyle, 'execfile' не запускает отдельный процесс, и он ** делает ** уважение к текущему рабочему каталогу. Редактирование моего ответа, чтобы показать простой пример, доказывающий, что вы ошибаетесь. –

Смежные вопросы