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

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

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
Комментарии к вопросу (4)
Решение

Вы можете перезагрузить модуль, если он уже был импортирован, с помощью встроенной функции 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'development server, используют это, чтобы вы могли видеть эффекты изменений вашего кода без перезапуска самого серверного процесса.

Цитирую из документации:

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

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

Комментарии (17)

В Python 3.0–3.3 можно использовать: чертенок.перезагрузка(модуля)

В BDFL и ответы этот вопрос.

Однако, чертенок была отменена в 3.4, в пользу importlib (спасибо @Стефан!).

Я думаю, поэтому ты теперь использовать importlib.перезагрузка(модуля), хотя я не уверен.

Комментарии (8)

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

Комментарии (2)

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

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

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

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

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

Комментарии (7)
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
Комментарии (2)

Для Python 2 использовать встроенные функции перезагрузка():

reload(module)

Для Python 2 и 3.2–3.3 использовать перезагрузка от ИМП модуль:

import imp
imp.reload(module)

Однако `бес`` устарел начиная с версии 3.4 в пользу importlib, так что используйте:

import importlib
importlib.reload(module)

или

from importlib import reload
reload(module)
Комментарии (2)

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

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

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

Комментарии (0)

Принято отвечать не'т обрабатывать от случая х Импорт г. Этот код обрабатывает его и стандартном случае импорта, а также:

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")

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

Комментарии (6)

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

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)

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

Во-первых, убедитесь, что вы используете превосходный оболочки IPython, от проекта ноутбука Jupyter. После установки Jupyter, вы можете запустить его с оболочкой IPython, иликонсоли jupyter, или даже лучше, - 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.
Комментарии (0)

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

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

Более подробная информация в модули перегрузочные в Python.

Комментарии (5)

Те, кто с помощью Python 3 и перезагрузить с importlib.

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

Комментарии (0)

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

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

Разработки enthought's пакет не'т перезагрузить файлы в момент их изменения - вы должны вызвать его явно, но что должно'т быть все, что трудно осуществить, если вы действительно в ней нуждается

Комментарии (0)

2018-02-01

  1. модуль фу должны быть успешно импортированы заранее.
  2. с импорт importlib перезагрузка,перезагрузка(ФОО)`

31.5. importlib — осуществление импортно — документации по языку Python 3.6.4

Комментарии (0)

Другой вариант. Вижу, что Python по умолчанию `importlib.релоад будет просто импортировать библиотеку передается в качестве аргумента. Это выиграл'т обновить библиотеки, что вашу библиотеку импорта. Если вы сменили много файлов и иметь довольно сложный пакет для импорта, вы должны сделать глубокая перезагрузка.

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

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

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

pip3 install jupyter
Комментарии (1)

для меня в случае комплекса 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)

Я получил много неприятностей пытается обновить что-то внутри возвышенный текст, но я смог наконец-то написал эту программу, чтобы обновить модули на возвышенное текст на основе кода 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 метод/функция () это будет перезагрузить файлы тестов. С возвышенное текст (питон 3.3.6) это происходит много, потому что его переводчик никогда не закрывается (только если вы перезапустите возвышенное текст, т. е. Питон3.3 переводчик).

Комментарии (0)

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

Комментарии (1)