У меня есть давно работающий сервер Python, и я хотел бы иметь возможность обновить службу без перезапуска сервера. Как лучше всего это сделать?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
Вы можете перезагрузить модуль, если он уже был импортирован, с помощью встроенной функции 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
.
В Python 3.0–3.3 можно использовать: чертенок.перезагрузка(модуля)
Однако, чертенок
была отменена в 3.4, в пользу importlib
(спасибо @Стефан!).
Я думаю, поэтому ты теперь использовать importlib.перезагрузка(модуля)
, хотя я не уверен.
Особенно трудно удалить модуль, если он не является чистым 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().
reload(module)
, но только если он полностью автономен. Если что-то еще имеет ссылку на модуль (или любой объект, принадлежащий модулю), то вы получите тонкие и любопытные ошибки, вызванные тем, что старый код висит дольше, чем вы ожидали, и такие вещи, как isinstance
не работают в разных версиях одного и того же кода.
Если у вас есть односторонние зависимости, вы также должны перезагрузить все модули, которые зависят от перезагружаемого модуля, чтобы избавиться от всех ссылок на старый код. А затем рекурсивно перезагрузить модули, которые зависят от перезагруженных модулей.
Если у вас есть круговые зависимости, что очень часто встречается, например, при перезагрузке пакета, вы должны выгрузить все модули в группе за один раз. Вы не можете сделать это с помощью reload()
, потому что он будет повторно импортировать каждый модуль до того, как его зависимости будут обновлены, что позволит старым ссылкам проникнуть в новые модули.
Единственный способ сделать это в данном случае - взломать sys.modules
, что вроде как не поддерживается. Вам придется пройтись и удалить каждую запись sys.modules
, которую вы хотите перезагрузить при следующем импорте, а также удалить записи, значения которых равны None
, чтобы решить проблему реализации, связанную с кэшированием неудачных относительных импортов. Это не очень приятно, но пока у вас есть полностью самодостаточный набор зависимостей, который не оставляет ссылок за пределами своей кодовой базы, это вполне работоспособно.
Возможно, лучше перезапустить сервер. :-)
Для 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)
Следующий код позволит вам с Python 2/3 совместимости:
try:
reload
except NameError:
# Python 3
from imp import reload
Вы можете использовать его как обновить () в обоих версиях, что делает вещи проще.
Принято отвечать не'т обрабатывать от случая х Импорт г. Этот код обрабатывает его и стандартном случае импорта, а также:
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")
В случае перегрузки, то переназначить имен высшего уровня со значениями, хранящимися в недавно перезагрузка модуль, который обновляет их.
Это современный способ перезарядки модуля:
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+
Чтобы использовать его, выполните перезагрузку(модуля)`, заменяют модуль с модуль вы хотите, чтобы перезагрузить.
Например, перезарядки(математика)обновит
математика` модуль.
Если вы не в сервере, но 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.
Для тех вроде меня, кто хочет выгрузить все модули (при работе в интерпретаторе Python в разделе в Emacs):
for mod in sys.modules.values():
reload(mod)
Более подробная информация в модули перегрузочные в Python.
Те, кто с помощью Python 3 и перезагрузить с importlib.
Если у вас есть такие проблемы, как кажется, что модуль не'т... перезагрузит это потому, что она нуждается в некотором времени, чтобы перекомпилировать ЧКД (до 60 сек).Я пишу это просто намек, что вы знаете, если вы столкнулись с этой проблемой.
Разработки enthought черты имеет модуль, который достаточно хорошо работает для этого. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Это позволит загрузить любой модуль, который был изменен, и обновление других модулей и изменяющиеся объекты, которые используют его. Он не работает большую часть времени с__очень_частная__` методов, и может подавиться наследование классов, но это спасает меня безумное количество времени до перезапуска приложения при написании PyQt GUI, как и материал, который проходит внутри таких программ, как Maya или Nuke. Это вовсе't работа может быть 20-30 % времени, но она's все еще невероятно полезно.
Разработки enthought's пакет не'т перезагрузить файлы в момент их изменения - вы должны вызвать его явно, но что должно'т быть все, что трудно осуществить, если вы действительно в ней нуждается
2018-02-01
фу
должны быть успешно импортированы заранее. ,
перезагрузка(ФОО)` 31.5. importlib — осуществление импортно — документации по языку Python 3.6.4
Другой вариант. Вижу, что Python по умолчанию `importlib.релоад будет просто импортировать библиотеку передается в качестве аргумента. Это выиграл'т обновить библиотеки, что вашу библиотеку импорта. Если вы сменили много файлов и иметь довольно сложный пакет для импорта, вы должны сделать глубокая перезагрузка.
Если у вас есть оболочкой IPython или Jupyter установлен, вы можете использовать функцию глубокой перезагрузки все библиотеки:
from IPython.lib.deepreload import reload as dreload
dreload(foo)
Если вы Don'т иметь Jupyter, установите его с помощью следующей команды в командной строке:
pip3 install jupyter
для меня в случае комплекса 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'])
Я получил много неприятностей пытается обновить что-то внутри возвышенный текст, но я смог наконец-то написал эту программу, чтобы обновить модули на возвышенное текст на основе кода 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
переводчик).