Python - выполнение функции в другом скрипте в дочерней папке
У меня есть мастер-скрипт, который выполняет несколько дочерних скриптов в подпапках основного каталога.
Иерархия папок выглядит так:
MyFolder\MasterScript.py
MyFolder\ChildOneScript\ChildOne.py
MyFolder\ChildTwoScript\ChildTwo.py
MyFolder\ChildThreeScript\ChildThree.py
Из MasterScript мне нужно вызвать функцию в ChildOne "myChildFunction" и передать в нее некоторые переменные. Проблема в том, что я не могу просто сделать
import ChildOneScript.ChildOne as ChildOne
ChildOne.myChildFunction
потому что есть другие сценарии, которые зависят от относительного пути ChildOne. Поэтому, если я импортирую ChildOne в каталог MyFolder из MasterScript и вызываю там функцию myChildFunction, я получаю ошибки трассировки, говорящие, что другие файлы не могут быть найдены. Это связано с ошибками другого упрямого программиста, который отказывается менять свой относительный путь вызовов, так как это много ручной работы.
Итак, есть ли способ вызвать myChildFunction из MasterScript и передать ему некоторые переменные?
Я знаю, что могу использовать subprocess.call и его аргумент cwd, чтобы изменить рабочий каталог, но я не могу понять, можно ли вызвать конкретную функцию myChildFunction и передать ее с помощью подпроцесса.
Изменить: возможно ли передать переменные с помощью execfile?
2 ответа
Вы всегда можете взломать его с os
модуль. Это не красиво, но, вероятно, это лучшее, что вы можете сделать, не переписывая код другого парня. Если вы будете часто использовать функции из других сценариев, я бы написал обертку для них, чтобы их было проще вызывать:
import sys
import os
def call_legacy_func(func, *args, **opts):
prev = os.path.abspath(os.getcwd()) # Save the real cwd
try:
# Get the child's physical location.
func_path = sys.modules[func.__module__].__file__
except:
# Die; we got passed a built-in function (no __file__)
# Or you could just call it, I guess: return func(*args, **opts)
return None
# Change to the expected directory and run the function.
os.chdir(func_path)
result = func(*args, **opts)
# Fix the cwd, and return.
os.chdir(prev)
return result
import ChildOneScript.ChildOne as ChildOne
call_legacy_func(ChildOne.myChildFunction, 0, 1, kwarg=False)
Можете ли вы уточнить вашу проблему? В частности, мне неясно, в чем заключается ваша проблема с макетом папки и импортом из подписок.
Например, если я создаю следующую структуру каталогов:
/example
__init__.py
master.py
/childone
__init__.py
childone.py
/childtwo
__init__.py
childtwo.py
Где __init__.py
Это просто пустые файлы, а исходные файлы выглядят следующим образом:
# master.py
from childone.childone import childone_fxn
from childtwo.childtwo import childtwo_fxn
print "Calling child one"
childone_fxn()
print "Calling child two"
childtwo_fxn()
-
# childone.py
def childone_fxn():
print "hello from child one"
-
def childtwo_fxn():
print "hello from child two"
Изнутри /example
Я могу тогда бежать master.py
и получить ожидаемый результат:
example $ python master.py
Calling child one
hello from child one
Calling child two
hello from child two
Конечно, вы можете использовать модуль подпроцесса, если хотите обрабатывать дочерние сценарии как любой другой исполняемый файл, но я не вижу никакой причины, по которой вы не сможете напрямую импортировать дочерние сценарии. Но, возможно, я неправильно понимаю ваш вопрос...