重新加载其他模块中导入的子模块

时间:2018-10-09 17:48:45

标签: python python-3.x reload python-importlib

我遇到以下问题,我将共享四个不同的.py文件,以更好地说明自己。我正在从spyder(不是jupyter),python 3.4运行代码。 我有一个主脚本“ master001.py”,可以从中执行代码。看起来像这样:

import sys
before = [str(m) for m in sys.modules]

from importlib import reload
import time
#from child001 import calculation as calc
import child001 
from child002 import calculation_two
from child003 import calculation_three

after = [str(m) for m in sys.modules]
print("########################")   
print([m for m in after if not m in before])
print("########################\n")




stop = False
while stop == False:
    print("\n\n\n\n\n\n\n")
    reload_child_one = input("reload child 1 function? Enter Y or N\n")
    reload_child_one = reload_child_one.lower()

    if reload_child_one == "y":
        print("Script will try to reload the calculation 1 / child 1 module.")
        time.sleep(1)
        reload(child001)



    reload_child_two = input("reload child 2 function? Enter Y or N\n")
    reload_child_two = reload_child_two.lower()

    if reload_child_two == "y":
        print("Script will try to reload the calculation 2 / child 2 module.")
        time.sleep(1)
        #reload(sys.modules[calculation_two.__module__])
        #del calculation_two
        #from child002 import calculation_two
        #__import__("child002", fromlist='calculation_two')
        calculation_two = reload(sys.modules["child002"]).calculation_two



    print("\n####################################################")
    a = input("Enter number that will be saved in variable 'a' or enter Q to quit prorgam\n")

    if a.lower() == "q" :
        stop = True
        print("\nFunction complted. Script will quit.")
        print("####################################################\n")
        time.sleep(2)

    else:
        try:
            a = int(a)

            print("Master - Launching Child function 'calculation'")
            b = child001.calculation(a)

            print("\nMaster - Inside Master file. Result = b = {}".format(b))
            print("####################################################\n")

            print("Master - Launching Child 2 function 'calculation_two' on input variable")
            c = calculation_two(a)     

            print("\nMaster - Inside Master file. Result = c = {}".format(c))            
            print("####################################################\n")

            print("Master - Launching child 3")
            calculation_three()
            time.sleep(2)

        except:
            print("input value was not a valid number. Please, try again.\n")
            print("####################################################\n")
            time.sleep(2)

master001.py调用child001.py进行简单的计算:

print("wassupp from child 1 !!!")

def calculation(a):

    print("\n----------------------------------------")
    print("Child 1 - function 'calculation' started.")
    print("Child 1 - Operation that will be executed is: input variable + 20")

    result = a + 20

    print("Child 1 - Returning result =  {}".format(result))
    print("----------------------------------------\n")
    return result

然后,master001.py调用child002.py,在其中执行另一个简单的计算:

print("wassupp from child 2 !!!")

def calculation_two(a):

    print("\n----------------------------------------")
    print("Child 2 - function  'calculation_two' started.")
    print("Child 2 - Operation that will be executed is: input variable + 200")

    result = a + 200

    print("Child 2 - Returning result =  {}".format(result))
    print("----------------------------------------\n")
    return result

到目前为止,一切都很好。最后,我有child003.py。在此模块中,我执行的计算实际上是从child002.py

导入的
from child002 import calculation_two

print("wassupp from child 3 !!!")

def calculation_three():

    print("\n----------------------------------------")
    print("Child 3 function - Calculation will use the one in child 2 applied to value '3'.!\n")

    result = calculation_two(3)

    print("Child 3 - result =  {}".format(result))
    print("----------------------------------------\n")
    return

从运行master001.py可以看到,当我使用

重新加载Calculation_two时
calculation_two = reload(sys.modules["child002"]).calculation_two
适用于calculation_two

child002.py运行,但是不会重新加载calculation_two调用的child003.py

更具体地说,如果您运行master001.py并且在手动输入任何内容之前更改calculation_two的内容,那么当系统提示您

reload child 1 function? Enter Y or N

您输入N,当系统提示您输入

reload child 2 function? Enter Y or N

您输入Y,您将看到child003.py返回的值不反映新的更新代码。

我阅读了How do I unload (reload) a Python module?How to reload python module imported using `from module import *`,它们非常有帮助,但是我找不到针对该特定问题的解决方案。

1 个答案:

答案 0 :(得分:1)

您的问题在于如何从child002导入函数:

from child002 import calculation_two

这将创建对child003中功能对象的引用,并且该引用未替换。 Python名称就像绑在对象上的字符串标签一样。您可以将多个标签绑定到一个对象,如果要与另一个对象替换,则必须确保重新绑定所有这些标签。

您从此开始:

sys.modules['child002']
    -> module object created from child002.py
        -> module.__dict__ (the module globals)
            -> module.__dict__['calculation_two']
                    |
                    |
                    +--> function object named calculation_two
                    |
                    |
            -> module.__dict__['calculation_two']
        -> module.__dict__ (the module globals)
    -> module object for child003.py
sys.modules['child003']

,然后当您重新加载child002模块时,Python将所有现有的全局变量替换为新对象,因此您现在拥有:

sys.modules['child002']
    -> module object created from child002.py
        -> module.__dict__ (the module globals)
            -> module.__dict__['calculation_two']
                    |
                    |
                    +--> *new* function object named calculation_two


                    +--> *old* function object named calculation_two
                    |
                    |
            -> module.__dict__['calculation_two']
        -> module.__dict__ (the module globals)
    -> module object for child003.py
sys.modules['child003']

因为calculation_two模块对象中的child003引用是一个独立的标签。

您必须手动替换该标签:

calculation_two = reload(sys.modules["child002"]).calculation_two
child003.calculation_two = calculation_two

或者您不能直接引用calculation_two,而只能引用child002模块:

import child002

# ...

def calculation_three():
    # ...
    result = child002.calculation_two(3)

此时您具有以下关系:

sys.modules['child002']
    -> module object created from child002.py
       ^ -> module.__dict__ (the module globals)
       |    -> module.__dict__['calculation_two']
       |            |
       |            |
       |            +--> function object named calculation_two
       |
       |
       +------------+
                    |
                    |
            -> module.__dict__['child002']
        -> module.__dict__ (the module globals)
    -> module object for child003.py
sys.modules['child003']

我建议您阅读Ned Batchelder's explanation of Python names and values以获得另一种观点。