У меня есть долго работающий сервер Python, и я хотел бы иметь возможность обновить службу без перезапуска сервера. Какой лучший способ сделать это?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Марк Харрисон
источник
источник
Ответы:
Вы можете перезагрузить модуль, когда он уже был импортирован, используя
reload
встроенную функцию (только Python 3.4+) :В Python 3
reload
был перенесен вimp
модуль. В 3.4imp
был объявлен устаревшим в пользуimportlib
, иreload
был добавлен к последнему. При нацеливании на 3 или более позднюю версию, либо обращайтесь к соответствующему модулю при вызове,reload
либо импортируйте его.Я думаю, что это то, что вы хотите. Веб-серверы, такие как сервер разработки Django, используют это для того, чтобы вы могли видеть последствия изменений вашего кода без перезапуска самого процесса сервера.
Цитировать из документов:
Как вы отметили в своем вопросе, вам придется реконструировать
Foo
объекты, еслиFoo
класс находится вfoo
модуле.источник
is_changed
функция - произвольная функция, которую вы должны написать; это не встроенный. Например, он может открыть файл, соответствующий импортируемому модулю, и сравнить его с кэшированной версией, чтобы увидеть, изменился ли он.В Python 3.0–3.3 вы бы использовали:
imp.reload(module)
BDFL уже ответил на этот вопрос.
Тем не менее,
imp
был объявлен устаревшим в 3.4, в пользуimportlib
(спасибо @Stefan! ).Я думаю , поэтому, вы бы сейчас использовали
importlib.reload(module)
, хотя я не уверен.источник
reload(__builtins__)
действует в 2.xМожет быть особенно трудно удалить модуль, если он не является чистым Python.
Вот некоторая информация из: Как мне действительно удалить импортированный модуль?
источник
setattr(package, "empty", None)
reload()
перезагружает только самый верхний модуль, и все, что находится внутри него, не будет перезагружено, если вы сначала не удалите его из sys.modules.reload(module)
, но только если он полностью автономен. Если что-то еще имеет ссылку на модуль (или какой-либо объект, принадлежащий модулю), то вы получите тонкие и любопытные ошибки, вызванные старым кодом, зависшим дольше, чем вы ожидали, и такими вещами, какisinstance
не работа в разных версиях тот же кодЕсли у вас есть односторонние зависимости, вы также должны перезагрузить все модули, которые зависят от перезагруженного модуля, чтобы избавиться от всех ссылок на старый код. А затем перезагрузите модули, которые зависят от загруженных модулей, рекурсивно.
Если у вас есть циклические зависимости, которые очень распространены, например, когда вы имеете дело с перезагрузкой пакета, вы должны выгрузить все модули в группе за один раз. Вы не можете сделать это,
reload()
потому что он будет повторно импортировать каждый модуль до того, как будут обновлены его зависимости, позволяя старым ссылкам проникать в новые модули.Единственный способ сделать это в этом случае - взломать
sys.modules
, что не поддерживается. Вам нужно будет пройти и удалить каждуюsys.modules
запись, которую вы хотите перезагрузить при следующем импорте, а также удалить записи, значения которых относятсяNone
к проблеме реализации, связанной с кэшированием неудачных относительных импортов. Это не очень приятно, но пока у вас есть полностью автономный набор зависимостей, который не оставляет ссылок вне своей кодовой базы, это работоспособно.Вероятно, лучше перезагрузить сервер. :-)
источник
None
значениями, потому что я работаю именно с этой проблемой: я удаляю элементы изsys.modules
и после повторного импорта некоторые импортированные зависимостиNone
.None
записи смогли вернуться через механизм импорта, когда «реальные» записи были удалены, и я не могу этого добиться в 2.7; в будущем, конечно, это больше не проблема, поскольку неявный относительный импорт исчез. А пока удаляем все записи сNone
значением, похоже, исправляет это.reload
функцию? Он встроен, вам не нужно импортировать какую-либо библиотеку.источник
nose.run()
, даже послеreload(my_module)
%run my_module
[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
.import sys; import json; del sys.modules['json']; print(json.dumps([1]))
и модуль json все еще работает, хотя его больше нет в sys.modules.Для Python 2 используйте встроенную функцию reload () :
Для Python 2 и 3.2–3.3 используйте reload из модуля imp :
Но
imp
не рекомендуется с версии 3.4 в пользу importlib , поэтому используйте:или
источник
from six import reload_module
(надоpip install six
сначала конечно)from six.moves import reload_module
( doc )Следующий код обеспечивает совместимость с Python 2/3:
Вы можете использовать его как
reload()
в обеих версиях, что упрощает работу.источник
Принятый ответ не обрабатывает случай импорта X из Y. Этот код обрабатывает его, а также стандартный случай импорта:
В случае перезагрузки мы переназначаем имена верхнего уровня значениям, хранящимся во вновь загруженном модуле, который обновляет их.
источник
>>> from X import Y
перезагрузки сделать>>> __import__('X', fromlist='Y')
fromlist='*'
?from
в операторах импорта. Просто откровенныйimport <package>
и явный package.symbol в коде. Осознайте, что это не всегда возможно или желательно. (Вот одно исключение: из будущего импорта print_function.)foo = reload(foo); from foo import *
Это современный способ перезагрузки модуля:
Если вы хотите поддерживать версии Python старше 3.5, попробуйте это:
Чтобы использовать его, запустите
reload(MODULE)
, заменивMODULE
на модуль, который вы хотите перезагрузить.Например,
reload(math)
перезагрузитmath
модуль.источник
from importlib import reload
. Тогда вы можете сделатьreload(MODULE_NAME)
. Там нет необходимости для этой функции.modulereload(MODULE_NAME)
это более очевидно, чем просто,reload(MODULE_NAME)
и у него меньше шансов конфликтовать с другими функциями.Если вы не на сервере, но разрабатываете и вам нужно часто перезагружать модуль, вот хороший совет.
Во-первых, убедитесь, что вы используете превосходную оболочку IPython из проекта Jupyter Notebook. После установки Jupyter вы можете запустить его
ipython
, илиjupyter console
, или даже лучшеjupyter qtconsole
, что даст вам красивую раскрашенную консоль с дополнением кода в любой ОС.Теперь в вашей оболочке введите:
Теперь каждый раз вы запускаете ваш скрипт, ваши модули будут перезагружаться.
Помимо
2
, есть и другие варианты магии автозагрузки :источник
Для таких как я, которые хотят выгрузить все модули (при работе в интерпретаторе Python под Emacs ):
Больше информации в Перезагрузке модулей Python .
источник
sys.modules.values()
модуле. Например: >>> type (sys.modules.values () [1]) <class 'email.LazyImporter'> Так что, если я пытаюсь запустить этот код, он падает (я знаю, что это не практическое решение, просто указывая на это).if mod and mod.__name__ != "__main__": imp.reload(mod)
Enthought Traits имеет модуль, который довольно хорошо работает для этого. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Он перезагрузит любой модуль, который был изменен, и обновит другие модули и экземпляры, которые его используют. Это не работает большую часть времени с
__very_private__
методами и может подавить наследование классов, но это избавляет меня от сумасшедших затрат времени от необходимости перезапускать хост-приложение при написании PyQt-приложений или вещи, которые запускаются внутри таких программ, как Maya или Nuke. Это не работает, может быть, 20-30% времени, но все равно невероятно полезно.Пакет Enthought не перезагружает файлы в тот момент, когда они меняются - вы должны называть это явно - но это не должно быть так сложно реализовать, если вам это действительно нужно
источник
Те, кто использует Python 3 и перезагрузить из importlib.
Если у вас есть проблемы, такие как кажется, что модуль не перезагружается ... Это потому, что ему нужно некоторое время для перекомпиляции pyc (до 60 секунд). Я пишу этот совет только для того, чтобы вы знали, если у вас возникли проблемы такого рода.
источник
2018-02-01
foo
должен быть успешно импортирован заранее.from importlib import reload
,reload(foo)
31.5. importlib - Реализация импорта - документация Python 3.6.4
источник
Другой вариант. Обратите внимание, что Python по умолчанию
importlib.reload
просто повторно импортирует библиотеку, переданную в качестве аргумента. Он не перезагрузит библиотеки, которые импортирует ваша библиотека. Если вы изменили много файлов и у вас есть несколько сложный пакет для импорта, вы должны выполнить глубокую перезагрузку .Если у вас установлен IPython или Jupyter , вы можете использовать функцию для глубокой перезагрузки всех библиотек:
Если у вас нет Jupyter, установите его с помощью этой команды в вашей оболочке:
источник
reload() argument must be module
. Я использую пользовательскую функцию импорта и, похоже, не работает. Использование встроенных модулей работает. :-( перезагружать iPython - пустая трата времени для каждого небольшого изменения, которое я внес в свой код ...Изменить (Ответ V2)
Предыдущее решение хорошо просто для получения информации о сбросе, но оно не изменит все ссылки (больше, чем
reload
требуется, но меньше). Чтобы на самом деле установить все ссылки, я должен был пойти в сборщик мусора и переписать ссылки там. Теперь это работает как шарм!Обратите внимание, что это не будет работать, если GC выключен или если загружаются данные, которые не контролируются GC. Если вы не хотите связываться с GC, вам может быть достаточно оригинального ответа.
Новый код:
Оригинальный ответ
Как написано в ответе @ bobince, если в другом модуле уже есть ссылка на этот модуль (особенно если он был импортирован с
as
ключевым словом likeimport numpy as np
), этот экземпляр не будет перезаписан.Это оказалось весьма проблематично для меня , когда применение тестов , которые требуют «чистого листа» состояние модулей конфигурации, поэтому я написал функцию с именем ,
reset_module
который используетimportlib
«ыreload
функции и рекурсивно перезаписывает все атрибуты Заявленная модуля. Он был протестирован с версией Python 3.6.Примечание: используйте с осторожностью! Использование их в не периферийных модулях (например, в модулях, которые определяют классы, используемые извне) может привести к внутренним проблемам в Python (таким как проблемы выбора / отмены выбора).
источник
для меня для случая Abaqus это так, как это работает. Представьте, что ваш файл Class_VerticesEdges.py
источник
У меня было много проблем при попытке перезагрузить что-то внутри Sublime Text, но, наконец, я смог написать эту утилиту для перезагрузки модулей в Sublime Text на основе кода,
sublime_plugin.py
используемого для перезагрузки модулей.Это ниже позволяет вам перезагрузить модули из путей с пробелами в их именах, а затем после перезагрузки вы можете просто импортировать как обычно.
Если вы запускаете в первый раз, это должно загрузить модуль, но если позже вы сможете снова запустить метод / функцию,
run_tests()
он перезагрузит тестовые файлы. С Sublime Text (Python 3.3.6
) это часто происходит, потому что его интерпретатор никогда не закрывается (если вы не перезапустите Sublime Text, то естьPython3.3
интерпретатор).источник
Другим способом может быть импорт модуля в функцию. Таким образом, когда функция завершает работу, модуль получает мусор.
источник
sys.modules
.