如何在Django Shell中重新加载模块?


90

我正在使用Django,并一直使用Django Shell。烦人的部分是,虽然Django服务器在代码更改时重新加载,而Shell却没有,所以每次我对要测试的方法进行更改时,我都需要退出该Shell并重新启动它,重新导入所有我使用的模块需要,重新初始化我需要的所有变量等。尽管iPython历史记录节省了很多打字工作,但这仍然很痛苦。有没有办法使django shell自动重载,就像django开发服务器一样?

我了解reload(),但是我导入了许多模型并且通常使用from app.models import *语法,因此reload()并没有太大帮助。


2
您应该更新此问题,以将“ django-extensions”答案标记为正确。
woodardj

1
直到它对我真正起作用。我已经安装了扩展程序,并且代码都没有自动重载,而且在shell_plus文档中也没有提到自动重载。看来runserver_plus命令中有一个重新加载器,但这不是我想要的。
Mad Wombat

Answers:


37

我建议使用dongweiming所述的django-extensions项目。但是,不仅要使用“ shell_plus”管理命令,还应使用:

manage.py shell_plus --notebook

这将在您的Web浏览器上打开一个IPython笔记本。将您的代码写入单元格,导入等中并运行它。

更改模块时,只需单击笔记本菜单项“内核->重新启动”

到这里,您的代码现在正在使用修改后的模块。


30
“仅使用python笔记本”不是对OP问题的答案。
J__

这种方法虽然不像%autoreload那样是自动的,但比autoreload更可靠地工作。内核重启可确保笔记本计算机中的所有单元均获得完全重新加载的模块。另外,您可以选择重新启动并运行所有单元。
安东·西波斯

71

我建议使用IPython自动重载扩展

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

从现在开始,所有导入的模块将在评估之前进行刷新。

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

如果在%load_ext autoreload命令之前导入了某些内容,也可以使用。

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

也可能通过%aimport命令和3种自动重装策略阻止某些导入刷新:

%自动重载

  • 现在自动重新加载所有模块(%aimport排除的模块除外)。

%自动重载0

  • 禁用自动重新加载。

%自动重装1

  • 每次执行键入的Python代码之前,都要重新加载所有用%aimport导入的模块。

%自动重装2

  • 每次执行键入的Python代码之前,请重新加载所有模块(%aimport排除的模块除外)。

%aimport

  • 列出要自动导入或不导入的模块。

%aimport foo

  • 导入模块'foo'并将其标记为%autoreload 1自动重新加载

%aimport -foo

  • 将模块“ foo”标记为不自动重新加载。

这通常对我有用,但有一些警告:

  • 替换代码对象并不总是成功:将类中的@property更改为普通方法或将方法更改为成员变量会导致问题(但仅限于旧对象)。
  • 在重新加载模块之前从模块中删除(例如,通过猴子修补)的功能不会升级。
  • C扩展模块无法重新加载,因此无法自动重新加载。

2
如果您使用的是django的/manage.py shell_plus...如果您输入%load_ext autoreload,然后输入%autoreload 2,则会自动重新加载模型。
融合


请注意,显然,您需要为此安装ipython。参见例如stackoverflow.com/a/47170195/50899
Rabarberski

38

查看django-extensions项目提供的manage.py shell_plus命令。它将在启动外壳时加载所有模型文件。并自动重新加载您的任何修改,但不需要退出,您可以直接在那里调用


40
我使用shell_plus,我的模型没有自动重新加载,我缺少什么吗?
Diego Ponciano 2014年

30
shell_plus不会重新加载模型,因此这不能回答问题。
aljabear 2015年

5
如前所述,shell_plus不会重新加载模型。
zenperttu 2015年

2
也许我缺少了一些东西,但是shell_plus不会为我重新加载任何东西。它会在启动时加载所有模型,这很方便,但仅此而已。
Mad Wombat

13
shell_plus可以使用自动重载模块重载模块。输入'%load_ext autoreload',然后输入'%autoreload 2'-
bbrame

37

我的解决方案是编写代码并保存到文件,然后使用:

python manage.py shell <test.py

因此,我可以进行更改,然后保存并再次运行该命令,直到修复要修复的内容为止。


2
漂亮又简单。注意,添加exit()到py文件的底部以更简洁的方式退出Django shell。谢谢。
Marc

简单而优雅的解决方案。做得好。
尼科斯基普

25

似乎对此主题的普遍共识是python reload()很烂,并且没有很好的方法来做到这一点。


不正确 上面的@dongweiming答案是解决方案,应该被认为是最佳答案。
Joseph Sheedy

3
他回答说多评论说,shell_plus不会重新加载模型
疯狂袋熊

1
我自己进行了测试,并且不会重新加载。此外,我手工导入的非模型代码又如何呢?
Mad Wombat

我正在使用的应用程序中的类现在可以很好地重新加载(Python 3.4.3,Django 1.9b1,django扩展1.5.9),包括一个普通的非django-model模块和其中的类。距此答案已有5年了,并且已经发生了许多发展。
约瑟夫·希迪

1
我已经在40分钟前的设置中尝试过了,而shell_plus不会为我重新加载任何内容。Django 1.7.10,python 3.4.3,django扩展1.5.9。
Mad Wombat


5

对于这种不便之处,我的解决方案如下。我正在使用IPython。

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

对于Python 3.x,必须使用以下命令导入“ reload”:

from importlib import reload

希望能帮助到你。当然是出于调试目的。

干杯。


2

shell_plus与ipython配置一起使用。这将autoreload在shell_plus自动导入任何内容之前启用。

pip install django-extensions
pip install ipython
ipython profile create

编辑您的ipython个人资料(~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

打开一个外壳-请注意,您不需要包括--ipython

python manage.py shell_plus

现在,在SHELL_PLUS_PRE_IMPORTSSHELL_PLUS_POST_IMPORTSdocs)中将自动重新加载!

请注意,如果您的外壳程序在pdb.set_trace()保存文件时位于调试器(ex )上,则可能会干扰重新加载。


1
谢谢你的回答。但是,您可能会注意到,我在2010年问过它。很高兴得知八年后自动重装终于在shell_plus中起作用了:)
Mad Wombat

1

您可以像这样设置管理命令并每次重新运行,而不是从Django Shell运行命令。


0

不完全是您想要的,但是我现在倾向于自己构建用于测试和摆弄事物的管理命令。

在命令中,您可以按照自己的方式设置一堆本地语言,然后放入交互式shell中。

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

无需重新加载,但可以轻松轻松地进行交互式Django功能测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.