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       

Конечно, вы можете использовать модуль подпроцесса, если хотите обрабатывать дочерние сценарии как любой другой исполняемый файл, но я не вижу никакой причины, по которой вы не сможете напрямую импортировать дочерние сценарии. Но, возможно, я неправильно понимаю ваш вопрос...

Другие вопросы по тегам