我知道如何在常规Python解释器会话中重新加载常规Python模块。这个问题记录了如何做得很好:
How do I unload (reload) a Python module?
出于某种原因,我在Django的“manage.py shell”解释器会话中遇到了麻烦。要重新创建我的问题,请启动此处的基本Django教程:
Writing your first Django app, part 1
创建“民意调查”应用程序和“民意调查”类后,通过“manage.py shell”启动解释器并将“民意调查”应用程序导入其中。
import polls.models as pm
创建一个新的“民意调查”对象:
p = pm.Poll()
到目前为止一切顺利。现在回到您的源代码并添加任意方法或属性。例如,我添加了:
def x(self):
return 2+2
现在回到解释器并“重新加载”模块:
reload(pm)
现在尝试使用您的新方法或属性:
p1 = pm.Poll()
p1.x()
你会收到这条消息:
'Poll' object has no attribute 'x'
是什么给出的?我还尝试重新运行import命令,使用不同的语法导入模块,删除对任何“Poll”对象或“Poll”类的所有引用。我也尝试过使用IPython解释器和普通的Python(v2.6)解释器。似乎没什么用。
在常规解释器会话中使用与任意Python模块相同的技术可以很好地工作。我似乎无法让它在Django的“shell”会话中工作。
顺便说一句,如果它有任何区别,我在Ubuntu 9.04机器上这样做。
答案 0 :(得分:38)
import os
from django.db.models.loading import AppCache
cache = AppCache()
curdir = os.getcwd()
for app in cache.get_apps():
f = app.__file__
if f.startswith(curdir) and f.endswith('.pyc'):
os.remove(f)
__import__(app.__name__)
reload(app)
from django.utils.datastructures import SortedDict
cache.app_store = SortedDict()
cache.app_models = SortedDict()
cache.app_errors = {}
cache.handled = {}
cache.loaded = False
我已将所有这些放在我的Django站点的根目录中名为reloadmodels.py的单独文件中。使用IPython我可以通过运行来重新加载所有内容:
%run ~/mysite/reloadmodels.py
答案 1 :(得分:6)
您还可以使用以下命令使用django-extensions项目:
manage.py shell_plus --notebook
这将在您的Web浏览器上打开一个IPython笔记本,而不是IPython shell解释器。在那里编写代码并运行它。
更改模块时,只需单击网页菜单项'Kernel-> Restart'
现在重新运行代码会使用您修改过的模块。
答案 2 :(得分:5)
假设您的项目以这种方式设置
首次加载
from bookstore.shelf.models import Books
后续重新加载
import bookstore;reload(bookstore.shelf.models);from bookstore.shelf.models import Books
答案 3 :(得分:5)
就我而言,上述解决方案都没有自行解决,this线程本身也没有多大帮助,但在结合这些方法后,我设法重新加载我的模型{ {3}}:
models.pyc
清理Django模型缓存(如shell_plus):
from django.db.models.loading import AppCache
cache = AppCache()
from django.utils.datastructures import SortedDict
cache.app_store = SortedDict()
cache.app_models = SortedDict()
cache.app_errors = {}
cache.handled = {}
cache.loaded = False
重新加载here
之类的模型reload(project.app.models)
from project.app.models import MyModel
答案 4 :(得分:5)
2016年我的解决方案(将来可能会更改)
1.安装django_extension
2.添加下一个设置:
SHELL_PLUS = 'ipython'
IPYTHON_ARGUMENTS = [
'--ext', 'autoreload',
]
3.Run shell
./manage.py shell_plus
模型示例
class Notification(models.Model):
........
@classmethod
def get_something(self):
return 'I am programmer'
在shell中
In [1]: Notification.get_something()
Out[1]: 'I am programmer'
对模型进行了更改
@classmethod
def get_something(self):
return 'I am Python programmer'
在shell中
# shell does not display changes
In [2]: Notification.get_something()
Out[2]: 'I am programmer'
在shell中。这是一个神奇的
# configure extension of ipython
In [3]: %autoreload 2
在shell中
# try again - all worked
In [4]: Notification.get_something()
Out[4]: 'I am Python programmer'
再次进行更改
@classmethod
def get_something(self):
return 'I am full-stack Python programmer'
在shell中
# all worked again
In [5]: Notification.get_something()
Out[5]: 'I am full-stack Python programmer'
缺点: 1.需要手动运行代码
%autoreload 2
因为django_extension 1.7不支持运行任意代码。可能在将来的版本中它具有此功能。
注意:
答案 5 :(得分:3)
ipython console每个reload()
表达式都会deep reload;当然还增加了许多其他有用的东西。
答案 6 :(得分:2)
pip install ipython
python manage.py shell
:行首的符号现在应为In [1]:
(cmd为>>>
)ipython profile create
进入~/.ipython/profile_default/ipython_config.py
并在文本编辑器中打开它,并在最后添加这两行:
c.InteractiveShellApp.extensions = [' autoreload']
c.InteractiveShellApp.exec_lines = ['%autoreload 2']
您现在可以运行python manage.py shell
,无需编写%autoreload 2
答案 7 :(得分:1)
在导入任何代码之前启用IPython自动加载扩展:
%load_ext autoreload
%autoreload 2
我将它与常规的django shell一起使用,虽然它确实有一些局限性,但它可以很好地工作:
<强> *注意事项:强>
以可靠的方式重新加载Python模块通常很困难,并且可能会发生意外情况。 %autoreload尝试通过用新版本替换模块中先前的函数代码对象和类的部分来解决常见的陷阱。这使得以下工作成为可能:
一些已知的警告是:
来源:https://ipython.org/ipython-doc/3/config/extensions/autoreload.html#caveats
另一个很好的选择是在单独的脚本中编写代码并将其发送到django shell,如下所示:
manage.py shell < my_script.py
答案 8 :(得分:0)
我无法获得上述任何解决方案,但我确实想出了一个解决方法,用于在我的django项目中重新加载任何其他非模型模块(例如functions.py
或{{1模块)。
创建名为views.py
的文件。我将它存储在我的开发机器上的django项目的reimport_module.py
文件夹中。
local/
启动shell plus(使用嵌入式IPython shell):
# Desc: Imports the module with the name passed in, or imports it for first
# time if it hasn't already been imported.
#
# Purpose of this script is to speed up development of functions that
# are written in an external editor then tested in IPython.
#
# Without this script you have to exit & reenter IPython then redo
# import statements, definitions of local variables, etc.
#
# Note: doesn't work for Django models files, because Django caches
# them in a structure called AppCache.
#
# Args: module to reload (string)
import sys
module_to_reload = sys.argv[1]
# Attempt to pop module
try:
sys.modules.pop(module_to_reload)
print 'reimporting...'
except KeyError:
print 'importing for first time...'
# (re)import module
import_str = 'from {0} import *'.format(module_to_reload)
exec(import_str)
使用以下命令导入您正在开发的模块:
python manage.py shell_plus
使用IPython测试模块中的函数。
使用以下命令重新导入模块,而无需退出&amp;重新进入IPython:
%run local/reimport_module.py 'your.module'
注意:此命令已在步骤3中使用,因此您可以键入%run local/reimport_module.py 'your.module'
,然后点击向上箭头以自动填充它。