Перезагрузка локального модуля не работает

Во-первых, я знаю, что это было опубликовано ранее, но либо A) рекомендации не работают, либо B) рекомендуется вручную удалить модуль из пространства имен и повторно импортировать его, как обычно.

У меня есть следующая структура модуля

basedir/
    pytools/
        __init__.py
        tools.py
    setup.py
    test.py

Если я в basedir, импортирую pytools и создаю объект класса testcls. Фактические свойства класса находятся в tools.py. testcls имеет метод testfunc, который прямо сейчас просто выводит AAA:

>>> import pytools
>>> test = pytools.testcls()
>>> test.testfunc()
AAA

Допустим, я изменил testfunc(), чтобы теперь распечатать BBB. Я делаю это и сохраняю файл. Затем я перезагружаю модуль и пытаюсь снова, он не печатает BBB:

>>> from importlib import reload
>>> reload(pytools)
>>> test = pytools.testcls()
>>> test.testfunc()
AAA

Однако если я сделаю тот же самый процесс, но вместо этого изменю test.py, импортирую этот файл как модуль, отредактирую функцию внутри него и перезагрузлю его, он будет вести себя так, как ожидалось:

>>> import test
>>> testvariable = test.testcls()
>>> testvariable.testfunc2()
AAA
# Change the function here
>>> from importlib import reload
>>> reload(test)
>>> testvariable = test.testcls()
>>> testvariable.testfunc2()
BBB

Я действительно не понимаю, что происходит, и это просто очень раздражает меня в этот момент. Это также стоило мне немало времени, но сейчас я больше раздражен.

Любые идеи, что происходит??

Версии:

Питон: 3.6.5

Интерпретатор: IPython, 6.2.1


person James Wright    schedule 25.06.2018    source источник
comment
хм, я не уверен, что смогу помочь, но когда вы перезагружаетесь, переменная test (test = pytools.testcls()) все еще находится в пространстве имен? В этом случае это может повлиять на перезагрузку. Может попробовать удалить test и перезагрузить? Извините, если это не поможет - я пишу больше по наитию, чем по опыту.   -  person Roberto    schedule 25.06.2018
comment
Каково содержимое __init__.py?   -  person jedwards    schedule 25.06.2018
comment
У вас должно быть что-то в __init__.py, иначе вы получите AttributeError: module 'pytools' has no attribute 'testcls', поэтому, пожалуйста, отредактируйте свой вопрос и покажите его содержание , слишком.   -  person martineau    schedule 25.06.2018


Ответы (1)


Назовем вещи более обобщенно:

basedir/
    testpackage/
        __init__.py
        testmodule.py
    test.py

Если testmodule.py содержит:

class TestClass:
    def test_method(self):
        print("AAA")

Затем следующее работает, как вы ожидаете:

>>> from testpackage import testmodule
>>> obj = testmodule.TestClass()
>>> obj.test_method()
DDD
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testmodule)
>>> obj = testmodule.TestClass()
>>> obj.test_method()
EEE

Но если __init__.py имеет что-то вроде:

from .testmodule import TestClass

И вы пытаетесь импортировать (и перезагружать) пакет, а не модуль, происходит следующее:

>>> import testpackage
>>> obj = testpackage.TestClass()
>>> obj.test_method()
EEE
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testpackage)
>>> obj = testpackage.TestClass()
>>> obj.test_method()
EEE

(Это без изменений)

Обратите внимание на следующий раздел документации:

Если модуль импортирует объекты из другого модуля, используя from … import …, вызов reload() для другого модуля не переопределяет импортированные из него объекты — один способ обойти это — повторно выполнить оператор from, другой — использовать import и вместо этого полные имена (module.name).

Если бы вы перезагрузили оба модуль и пакет в указанном порядке, все снова заработало бы так, как вы ожидаете:

>>> import testpackage
>>> obj = testpackage.TestClass()
>>> obj.test_method()
HHH
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testpackage.testmodule)
>>> reload(testpackage)
>>> obj = testpackage.TestClass()
>>> obj.test_method()
III

Но это кажется глупым и подверженным ошибкам, просто используйте подход из первого примера:

from testpackage import testmodule
...
reload(testmodule)
... 
person jedwards    schedule 25.06.2018