Правильный способ перезагрузки модуля python с консоли
Я отлаживаю консоль python и хочу перезагружать модуль каждый раз, когда я делаю изменения, поэтому мне не нужно покидать консоль и повторно вводить ее. Я делаю:
>>> from project.model.user import *
>>> reload(user)
но я получаю:
>>>NameError: name 'user' is not defined
Каков правильный способ перезагрузки всего пользовательского класса? Есть ли лучший способ сделать это, возможно автоматическое обновление при отладке?
Спасибо.
Ответы
Ответ 1
Как и было задано, самое лучшее, что вы можете сделать, это
>>> 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
(ах, на территорию зла, в которой мы оказались), либо отдельный процесс.
Ответ 2
К сожалению, вы должны использовать:
>>> 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__"
Ответ 3
Вы не можете эффективно использовать reload().
Python не обеспечивает эффективную поддержку для перезагрузки или разгрузки ранее импортированных
модули; ссылки на модули делают невозможным перезагрузить модуль, потому что ссылки могут существовать во многих местах вашей программы.
Python 3 полностью удалил функцию reload().
Ответ 4
IPython может перезагружать модули перед выполнением каждой новой строки:
%load_ext autoreload
%autoreload 2
Где %autoreload 2
перезагружает "все модули (кроме тех, которые исключены% aimport) каждый раз перед выполнением введенного кода Python."
Смотрите документы:
Ответ 5
Для 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
Ответ 6
Вы также можете попробовать twisted.python.rebuild.rebuild
.