Перезагрузить субмодуль, импортированный в другие модули - PullRequest
0 голосов
/ 09 октября 2018

У меня следующая проблема, и я поделюсь четырьмя разными .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, когда я перезагружаю account_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 notотражая новый обновленный код.

Я прочитал Как выгрузить (перезагрузить) модуль Python? и Как перезагрузить импортированный модуль Python, используя `from import import *` они очень полезны, но я не могу найти там решения этой конкретной проблемы.

1 Ответ

0 голосов
/ 09 октября 2018

Ваша проблема в том, как вы импортировали функцию из 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']

Я могу рекомендовать прочитать объяснение Неда Батчелдера имен и значений Python для другого взгляда на это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...