список - перезагрузка модуля python




Как выгрузить(перезагрузить) модуль Python? (13)

2018-02-01

  1. модуль foo должен быть успешно импортирован.
  2. from importlib import reload , reload(foo)

31.5. importlib - реализация импорта - документация Python 3.6.4

У меня многолетний Python-сервер и вы хотите обновить сервис без перезагрузки сервера. Каков наилучший способ сделать это?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()

Enthought Traits имеет модуль, который работает достаточно хорошо для этого. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Он перезагрузит любой измененный модуль и обновит другие модули и объекты, которые его используют. Он не работает большую часть времени с __very_private__ методов __very_private__ и может __very_private__ наследование классов, но это избавляет меня от сумасшедшего времени от необходимости перезапуска приложения-хозяина при написании PyQt guis или материала, который запускается внутри таких программ, как Maya или Nuke , Это не работает, возможно, в 20-30% случаев, но это все еще невероятно полезно.

Пакет Enthoughtht не перезагружает файлы в тот момент, когда они меняются - вы должны называть это явно - но это не должно быть так сложно реализовать, если вам это действительно нужно


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

from importlib import reload  # Python 3.4+ only.
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

В Python 3 reload была перенесена в модуль imp . В 3.4, imp был устаревшим в пользу importlib , и к последнему добавилась reload . При таргетинге 3 или более поздней версии либо ссылайтесь на соответствующий модуль, когда вы вызываете reload или импортируете его.

Я думаю, что это то, что вы хотите. Веб-серверы, такие как сервер разработки Django, используют это, чтобы вы могли видеть эффекты изменений кода без перезапуска самого процесса сервера.

Цитировать из документов:

Код модулей Python перекомпилируется, а код модуля-уровня повторно выполняется, определяя новый набор объектов, привязанных к именам в словаре модуля. Функция init модулей расширения не вызывается второй раз. Как и все другие объекты в Python, старые объекты восстанавливаются только после того, как их отсчеты ссылок упадут до нуля. Имена в пространстве имен модулей обновляются, чтобы указывать на любые новые или измененные объекты. Другие ссылки на старые объекты (например, имена, внешние по отношению к модулю) не восстанавливаются, чтобы ссылаться на новые объекты и должны обновляться в каждом пространстве имен, где они встречаются, если это необходимо.

Как вы отметили в своем вопросе, вам придется восстанавливать объекты Foo если класс Foo находится в модуле foo .



Другой вариант. Посмотрите, что Python default importlib.reload просто importlib.reload библиотеку, переданную в качестве аргумента. Он не перезагрузит библиотеки, которые импортируют ваш lib. Если вы изменили много файлов и имеете несколько сложный пакет для импорта, вы должны сделать глубокую перезагрузку .

Если у вас установлен IPython или Jupyter , вы можете использовать функцию для глубокой перезагрузки всех lib:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

Если у вас нет Jupyter, установите его с помощью этой команды в своей оболочке:

pip3 install jupyter

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


Операцию unload можно легко выполнить следующим образом:

import pythonlib
del pythonlib

у вас больше ничего не будет связано с этой библиотекой.


Особенно сложно удалить модуль, если он не является чистым Python.

Вот некоторая информация из: Как действительно удалить импортированный модуль?

Вы можете использовать sys.getrefcount (), чтобы узнать фактическое количество ссылок.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

Числа, превышающие 3, показывают, что из модуля будет сложно избавиться. Домашний «пустой» (не содержащий ничего) модуль должен быть собран из мусора после

>>> del sys.modules["empty"]
>>> del empty

поскольку третья ссылка является артефактом функции getrefcount ().


Следующий код позволяет вам совместимость Python 2/3:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

Вы можете использовать его как reload() в обеих версиях, что упрощает работу.


Те, кто использует python 3 и перезагружают из importlib.

Если у вас есть проблемы, подобные тому, что кажется, что модуль не перезагружается ... Это потому, что для перекомпиляции pyc (до 60 секунд) требуется некоторое время. Я пишу этот намек только для того, чтобы вы знали, что вы столкнулись с такой проблемой.


Это современный способ перезагрузки модуля:

from importlib import reload

Просто введите reload(MODULE_NAME) , заменив MODULE_NAME на имя модуля, который вы хотите перезагрузить.

Например, reload(math) перезагружает математическую функцию.


для меня в случае с Абакусом это так, как это работает. Представьте, что ваш файл - Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

if 'myModule' in sys.modules:  
    del sys.modules["myModule"]




python-import