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

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

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
706
13 янв. '09 в 3:33
источник поделиться
19 ответов

Вы можете перезагрузить модуль, когда он уже был импортирован, используя встроенную функцию 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.

662
13 янв. '09 в 3:34
источник

Связанные вопросы


Похожие вопросы

В Python 3.0-3.3 вы должны использовать: imp.reload(module)

BDFL имеет ответил на этот вопрос.

Однако imp устарел в 3.4, в пользу importlib (спасибо @Stefan!).

Я думаю, поэтому youd теперь используйте importlib.reload(module), хотя Im не уверен.

243
10 окт. '09 в 16:36
источник

Это может быть особенно сложно удалить модуль, если он не является чистым 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().

82
28 янв. '09 в 17:03
источник

reload(module), но только если он полностью автономный. Если что-либо еще имеет ссылку на модуль (или любой объект, принадлежащий модулю), то вы получите тонкие и любопытные ошибки, вызванные тем, что старый код висит дольше, чем вы ожидали, и такие вещи, как isinstance, не работают с разными версии одного и того же кода.

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

Если у вас есть циклические зависимости, что очень часто встречается, например, когда вы имеете дело с перезагрузкой пакета, вы должны разгрузить все модули в группе за один раз. Вы не можете сделать это с помощью reload(), потому что он будет повторно импортировать каждый модуль до того, как его зависимости будут обновлены, что позволит использовать старые ссылки для ползучести в новые модули.

Единственный способ сделать это в этом случае - взломать sys.modules, что является неподдерживаемым. Вам нужно будет пройти и удалить каждую запись sys.modules, которую вы хотели бы перезагрузить при следующем импорте, а также удалить записи, значения которых None для решения проблемы с реализацией, связанной с кэшированием, при неудачном относительном импорте. Это не очень приятно, но до тех пор, пока у вас есть полностью автономный набор зависимостей, который не оставляет ссылок за пределами его кодовой базы, он работоспособен.

Вероятно, лучше всего перезапустить сервер.: -)

62
13 янв. '09 в 15:53
источник
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
59
07 июля '10 в 14:44
источник

Для Python 2 используйте встроенную функцию reload():

reload(module)

Для Python 2 и 3.2-3.3 используйте перезагрузку из модуля imp:

import imp
imp.reload(module)

Но imp не рекомендуется с версии 3.4 в пользу importlib, поэтому используйте:

import importlib
importlib.reload(module)

или же

from importlib import reload
reload(module)
51
09 авг. '15 в 20:28
источник

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

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

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

21
20 нояб. '12 в 19:01
источник

Принятый ответ не обрабатывает случай X импорта Y. Этот код обрабатывает его и стандартный случай импорта:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

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

16
28 сент. '14 в 2:30
источник

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

from importlib import reload

Если вы хотите поддерживать версии Python старше 3.4, попробуйте это:

from sys import version_info
if version_info[0] < 3:
    pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
    from imp import reload # Python 3.0 - 3.4 
else:
    from importlib import reload # Python 3.5+

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

Например, reload(math) перезагрузит math модуль.

14
21 нояб. '17 в 21:04
источник

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

Во-первых, убедитесь, что вы используете превосходную оболочку IPython из проекта Jupyter Notebook. После установки Jupyter вы можете запустить его с ipython, или jupyter console, или, что еще лучше, с jupyter qtconsole, которая даст вам красивую раскрашенную консоль с дополнением кода в любой ОС.

Теперь в вашей оболочке введите:

%load_ext autoreload
%autoreload 2

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

Помимо 2, есть и другие варианты магии автозагрузки:

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.
10
18 марта '18 в 16:46
источник

Для таких, как я, которые хотят выгрузить все модули (при запуске в интерпретаторе Python под Emacs):

   for mod in sys.modules.values():
      reload(mod)

Дополнительная информация находится в Перезагрузка модулей Python.

7
08 мая '10 в 19:50
источник

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% случаев, но это все еще невероятно полезно.

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

5
09 янв. '16 в 4:06
источник

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

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

4
17 мая '18 в 14:00
источник

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

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

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

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

pip3 install jupyter
3
08 мая '18 в 21:07
источник

2018-02-01

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

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

3
01 февр. '18 в 6:44
источник

для меня в случае с Abaqus это так, как это работает. Представьте, что ваш файл 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'])
1
05 февр. '16 в 17:27
источник

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

0
12 февр. '15 в 0:13
источник

У меня много проблем с попыткой перезагрузить что-то внутри Sublime Text, но, наконец, я смог написать эту утилиту для перезагрузки модулей в Sublime Text на основе кода sublime_plugin.py для перезагрузки модулей.

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

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

Если вы запускаете в первый раз, это должно загрузить модуль, но если позже вы снова сможете использовать метод/функцию run_tests(), он перезагрузит файлы тестов. С Sublime Text (Python 3.3.6) это происходит очень часто, потому что его интерпретатор никогда не закрывается (если вы не перезапустите Sublime Text, т.е. Интерпретатор Python3.3).

0
09 нояб. '17 в 21:36
источник

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

import pythonlib
del pythonlib

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

-1
16 авг. '18 в 16:12
источник

Посмотрите другие вопросы по меткам или Задайте вопрос