Правильный способ перезагрузить модуль Python из консоли
Я отлаживаю с консоли Python и хотел бы перезагружать модуль каждый раз, когда я делаю изменения, чтобы мне не пришлось выходить из консоли и повторно вводить ее. Я делаю:
>>> from project.model.user import *
>>> reload(user)
но я получаю:
>>>NameError: name 'user' is not defined
Как правильно перезагрузить весь пользовательский класс? Есть ли лучший способ сделать это, возможно, автоматическое обновление во время отладки?
Благодарю.
6 ответов
Как и просили, лучшее, что вы можете сделать, это
>>> from project.models.user import *
>>> import project # get module reference for reload
>>> reload(project.models.user) # reload step 1
>>> from project.models.user import * # reload step 2
было бы лучше и чище, если бы вы использовали пользовательский модуль напрямую, а не делали import *
(что почти никогда не является правильным способом сделать это). Тогда это было бы просто
>>> from project.models import user
>>> reload(user)
Это будет делать то, что вы хотите. Но это не очень приятно. Если вам действительно нужно перезагружать модули так часто, я должен спросить: почему?
Мое подозрение (подкрепленное предыдущим опытом с людьми, задающими подобные вопросы) заключается в том, что вы тестируете свой модуль. Есть много способов проверить модуль, и сделать это вручную в интерактивном интерпретаторе - один из худших способов. Сохраните один из ваших сеансов в файл и используйте doctest
, для быстрого исправления. В качестве альтернативы, запишите его как программу и используйте python -i
, Единственное действительно отличное решение, однако, это использование unittest
модуль.
Если это не так, надеюсь, что-то лучше, а не хуже. Там действительно нет смысла использовать reload
(фактически, это удалено в 3.x). Это не работает эффективно - вы можете перезагрузить модуль, но оставить остатки от предыдущих версий. Он даже не работает со всеми видами модулей - модули расширения не будут перезагружаться должным образом, а иногда даже ужасно ломаться при перезагрузке.
Контекст использования его в интерактивном переводчике не оставляет большого выбора относительно того, что вы делаете, и каково будет действительно лучшее решение. За пределами этого люди иногда использовали reload()
реализовать плагины и т. д. Это в лучшем случае опасно, и часто может быть сделано по-другому exec
(ах та злая территория, на которой мы находимся), или отдельный процесс.
Для python3 перезагрузка перенесена в модуль imp. ты можешь использовать imp.reload()
, Вы можете сослаться на этот пост.
>>> import imp
>>> import project # get module reference for reload
>>> imp.reload(project.models.user) # reload step 1
>>> from project.models.user import * # reload step 2
IPython может перезагрузить модули перед выполнением каждой новой строки:
%load_ext autoreload
%autoreload 2
куда %autoreload 2
перезагружает "все модули (кроме исключенных%aimport) каждый раз перед выполнением набранного кода Python".
Смотрите документы:
Вы не можете использовать reload() эффективным способом.
Python не обеспечивает эффективной поддержки перезагрузки или выгрузки ранее импортированных модулей; ссылки на модули делают нецелесообразным перезагружать модуль, потому что ссылки могут существовать во многих местах вашей программы.
В Python 3 полностью удалена функция reload().
К сожалению, вы должны использовать:
>>> from project.model import user
>>> reload(user)
Я не знаю, во что бы то ни стало, что будет автоматически перезагружать модули в интерактивном режиме... Но я не вижу причин, по которым не следует существовать (на самом деле, это не будет слишком сложно реализовать, или…)
Теперь вы можете сделать что-то вроде этого:
from types import ModuleType
import sys
_reload_builtin = reload
def reload(thing):
if isinstance(thing, ModuleType):
_reload_builtin(thing)
elif hasattr(thing, '__module__') and thing.__module__:
module = sys.modules[thing.__module__]
_reload_builtin(module)
else:
raise TypeError, "reload() argument must be a module or have an __module__"
Начиная с Python 3.4 вы можете использовать importlib.reload(module)
>>> from importlib import reload
>>> from project.model import user
>>> reload(user)
from test_reload import add_test
где test_reload
это модуль, а add_test
это функция, если вы изменили функцию add_test
, конечно, вам нужно перезагрузить эту функцию. тогда вы можете сделать это:
import imp
imp.reload(test_reload)
from test_reload import add_test
это обновит функцию add_test
.
так что вам нужно добавить
imp.reload(test_reload)
from test_reload import add_test --add this line in your code