【问题标题】:How to reload modules in django shell?如何在 django shell 中重新加载模块?
【发布时间】:2011-04-15 21:28:54
【问题描述】:

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

我知道reload(),但是我导入了很多模型,一般使用from app.models import *语法,所以reload()没有太大帮助。

【问题讨论】:

  • 您应该更新此问题以标记“django-extensions”答案正确。
  • 直到它真正对我有用。我安装了扩展,我的代码都没有自动重新加载,我在 shell_plus 文档中没有看到任何关于自动重新加载的内容。 runserver_plus 命令中似乎有一个重新加载器,但这不是我要找的。​​span>

标签: python django ipython


【解决方案1】:

如果没有一些技巧,Reload() 在 Django shell 中不起作用。您可以查看此线程 na 和我的答案:

How do you reload a Django model module using the interactive interpreter via "manage.py shell"?

【讨论】:

    【解决方案2】:

    似乎对这个话题的普遍共识是,python reload() 很烂,没有好办法。

    【讨论】:

    • 不正确。 @dongweiming 上面的答案是解决方案,应该被接受为最佳答案。
    • 多个 cmets 在他的回答中说 shell_plus 不会重新加载模型
    • 我刚刚自己测试过它并没有重新加载。另外,我手动导入的非模型代码呢?
    • 我正在使用的应用程序中的类现在可以很好地重新加载(Python 3.4.3、Django 1.9b1、django-extensions 1.5.9),包括一个普通的非 django-model 模块和其中的类它。这个答案已经过去了 5 年,并且已经发生了很多发展。
    • 我在 40 分钟前在我的设置上尝试过它,但 shell_plus 没有为我重新加载任何东西。 Django 1.7.10,python 3.4.3,django-extensions 1.5.9。
    【解决方案3】:

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

    【讨论】:

    • 我使用 shell_plus 并且我的模型没有自动重新加载,我错过了什么吗?
    • shell_plus 不会重新加载模型,所以这不能回答问题。
    • 如前所述,shell_plus 不会重新加载模型。
    • 也许我遗漏了一些东西,但 shell_plus 并没有为我重新加载任何东西。它在启动时加载所有模型,这很方便,但仅此而已。
    • shell_plus CAN 使用自动重载模块重载模块。输入“%load_ext autoreload”,然后输入“%aut​​oreload 2”——见ipython.org/ipython-doc/3/config/extensions/autoreload.html
    【解决方案4】:

    您可以设置一个管理命令like so 并每次重新运行它,而不是从 Django shell 运行命令。

    【讨论】:

      【解决方案5】:

      我推荐使用上面 dongweiming 所说的 django-extensions 项目。但不要仅仅使用“shell_plus”管理命令,而是使用:

      manage.py shell_plus --notebook
      

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

      当你改变你的模块时,只需点击笔记本菜单项'Kernel->Restart'

      你去吧,你的代码现在正在使用你修改过的模块。

      【讨论】:

      • “仅使用 python 笔记本”不是 OP 问题的答案。
      • 这种方法虽然不像 %autoreload 那样自动,但确实比 autoreload 更可靠。内核重启保证笔记本中的所有单元都得到完全重新加载的模块。此外,如果您愿意,您可以重新启动并运行所有单元。
      【解决方案6】:

      不完全是你想要的,但我现在倾向于构建自己的管理命令来测试和摆弄东西。

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

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

      无需重新加载,而是一种简单且不那么烦人的交互式测试 django 功能的方法。

      【讨论】:

        【解决方案7】:

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

        python manage.py shell

        所以我可以进行更改,保存并再次运行该命令,直到我修复我要修复的任何内容。

        【讨论】:

        • 漂亮而简单。请注意,将exit() 添加到 py 文件的底部,以更简洁的方式退出 Django shell。谢谢。
        • 简单优雅的解决方案。干得好。
        【解决方案8】:

        我对这个不便的解决方案如下。我正在使用 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
        

        希望对您有所帮助。当然是为了调试。

        干杯。

        【讨论】:

          【解决方案9】:

          我建议使用 IPython autoreload extension

          ./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 个自动重载策略来阻止某些导入刷新:

          %autoreload

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

          %autoreload 0

          • 禁用自动重新加载。

          %autoreload 1

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

          %autoreload 2

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

          %aimport

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

          %aimport foo

          • 导入模块“foo”并将其标记为自动重新加载以用于 %autoreload 1

          %aimport -foo

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

          这通常适合我的使用,但有一些注意事项:

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

          【讨论】:

          • 如果你使用 django 的/manage.py shell_plus... 如果你输入%load_ext autoreload 然后%autoreload 2,模型将被自动重新加载。
          • 太棒了,你成就了我的一天
          • 请注意,您显然需要为此安装 ipython。参见例如stackoverflow.com/a/47170195/50899
          • 把这个 %autoreload 放在哪里?从答案中看不清楚
          【解决方案10】:

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

          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']
          

          打开一个shell - 注意你不需要包含--ipython

          python manage.py shell_plus
          

          现在SHELL_PLUS_PRE_IMPORTSSHELL_PLUS_POST_IMPORTS (docs) 中定义的任何内容都将自动重新加载!

          请注意,如果您的 shell 在您保存文件时处于调试器中(例如 pdb.set_trace()),则可能会干扰重新加载。

          【讨论】:

          • 感谢您的回答。不过你可能会注意到,我在 2010 年问过这个问题。我很高兴知道八年后自动重载终于在 shell_plus 中工作了 :)
          • 我试过了,没用,我还加了SHELL_PLUS_PRE_IMPORTSSHELL_PLUS_POST_IMPORTS
          • 这很整洁
          【解决方案11】:

          结合使用 2 个答案,我想出了一个简单的单行方法。

          您可以使用 -c 运行 django shell,这将运行您传递的命令,但是它会在代码运行后立即退出

          诀窍是设置您需要的内容,运行 code.interact(local=locals()),然后从您传递的代码中重新启动 shell。像这样:

          python manage.py shell -c 'import uuid;test="mytestvar";import code;code.interact(local=locals())'
          

          对我来说,我只是想要丰富库的检查方法。只有几行:

          python manage.py shell -c 'import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())'
          

          最后上面的樱桃是一个别名

          alias djshell='python manage.py shell -c "import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())"'
          

          现在,如果我启动我的 shell 并说,想要检查表单类,我会得到这个漂亮的输出:

          【讨论】:

            猜你喜欢
            • 2011-04-22
            • 2010-10-27
            • 2011-09-08
            • 2018-02-12
            • 2013-10-05
            • 2018-01-28
            • 2016-02-06
            • 2010-10-01
            相关资源
            最近更新 更多