Модуль перезагрузки, который был импортирован в другой модуль - программирование
Подтвердить что ты не робот

Модуль перезагрузки, который был импортирован в другой модуль

Посмотрим правде в глаза, весь процесс перезагрузки кода python после его изменения - беспорядок. Я немного сообразил, что вызов import <module> у интерпретатора лучше, чем from <module> import <class/function>, потому что тогда я могу вызвать reload(module), чтобы получить обновленный код.

Но у меня сейчас более сложные проблемы. Поэтому у меня есть этот файл module1.py, а наверху он говорит:

from module2 import <class1>, <function1>, etc.

И затем я иду и меняю код внутри модуля2. Оказывается, вызов reload(module1) не перезагружает код, измененный в модуле2, даже если код из модуля2 импортируется в верхней части модуля1. Есть ли способ перезагрузить все без перезапуска интерпретатора?

Прежде чем кто-нибудь узнает о моем стиле, я просто скажу, что:

  • Я вызываю reload только из интерпретатора, никогда в активном коде. Этот вопрос касается того, когда я тестирую новый код.
  • Я никогда не звоню из <module> import *, я знаю, что уничтожает читаемость
4b9b3361

Ответ 1

Посмотрите на IPython. Он имеет расширение autoreload, которое автоматически перезагружает модули во время сеанса интерпретатора перед вызовом функций внутри. Я приведу пример с целевой страницы:

In [1]: %load_ext autoreload

In [2]: %autoreload 2

In [3]: from foo import some_function

In [4]: some_function()
Out[4]: 42

In [5]: # open foo.py in an editor and change some_function to return 43

In [6]: some_function()
Out[6]: 43

Ответ 2

Чтобы перезагрузить модуль, вы должны использовать reload, и вы должны использовать его в модуле, который хотите перезагрузить. Перезагрузка модуля не рекурсивно перезагружает все модули, импортированные этим модулем. Он просто перезагружает этот один модуль.

Когда модуль импортируется, ссылка на него сохраняется, а затем импорт этого модуля повторно использует уже импортированную, уже сохраненную версию. Когда вы перезагружаете module1, он повторно запускает оператор from module2 import ..., но просто повторно использует уже импортированную версию module2 без перезагрузки.

Единственный способ исправить это - изменить код, чтобы он import module2 вместо (или в дополнение к) from module2 import .... Вы не можете перезагрузить модуль, если сам модуль не был импортирован и не привязан к имени (т.е. С оператором import module, а не только инструкцией from module import stuff).

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

>>> import module
>>> from module import x
>>> x
2
# Change module code here, changing x to 3
>>> reload(module)
>>> from module import x
>>> x
3

Это может быть удобно для интерактивной работы, поскольку оно позволяет использовать короткие, неперечисленные имена, чтобы ссылаться на то, что вам нужно, при этом все еще можно перезагрузить модуль.

Ответ 3

Хорошо, я не уверен, что квалифицируется как ответ без изменения кода, но... по крайней мере, это не связано с изменением на module1.

Вы можете использовать некоторый класс оболочки модуля, который сохраняет загруженные модули до и после загрузки модуля1 и который предоставляет метод reload, что-то вроде этого:

import sys

class Reloader(object):
    def __init__(self, modulename):
        before = sys.modules.keys()
        __import__(modulename)
        after = sys.modules.keys()
        names = list(set(after) - set(before))
        self._toreload = [sys.modules[name] for name in names]

    def do_reload(self):
        for i in self._toreload:
            reload(i)

Затем загрузите модуль1 с помощью

reloader = Reloader('module1')

Убедитесь, что вы можете изменить module2 и перезагрузить его в интерпретаторе с помощью

reloader.do_reload()

Ответ 4

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

$ python -i setup.py
>>>

Это запустит setup.py, а затем оставит вас в интерактивном приглашении. Или, вместо того, чтобы выполнять большую работу в интерактивном приглашении, напишите автоматизированные тесты, которые сделают вашу работу за вас.

Вы правы, перезагрузка модулей в Python - беспорядок. Семантика языка затрудняет изменение кода во время работы процесса. Научитесь не перегружать модули, вы будете счастливее.

Ответ 5

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

>>> reload(module2)
>>> module1.class1 = module2.class1

Теперь объект class1 внутри модуля1 относится к перезагруженной версии из модуля2.

Ответ 6

Вот рекурсивная функция перезагрузки, которую вы могли бы использовать (кредит для @Matthew): fooobar.com/info/328039/...