djangoシェルでモジュールをリロードする方法は?


90

私はDjangoを使用しており、常にDjangoシェルを使用しています。厄介なのは、Djangoサーバーはコードの変更時にリロードしますが、シェルはリロードしないため、テストしているメソッドに変更を加えるたびに、シェルを終了して再起動し、すべてのモジュールを再インポートする必要があります。必要、必要なすべての変数を再初期化するなど。iPythonの履歴により、これに関する入力の多くが節約されますが、これは依然として苦痛です。django開発サーバーと同じように、djangoシェルを自動リロードする方法はありますか?

私はreload()について知っていますが、多くのモデルをインポートし、通常はfrom app.models import *構文を使用するため、reload()はあまり役に立ちません。


2
この質問を更新して、「django-extensions」の回答を正解としてマークする必要があります。
woodardj 2013年

1
それが実際に私のために働くまでは。拡張機能がインストールされていますが、コードの自動再読み込みがなく、shell_plusドキュメントに自動再読み込みについての言及がありません。runserver_plusコマンドにリローダーがあるようですが、それは私が探しているものではありません。
マッドウォンバット2015

回答:


37

dongweimingが前述したようなdjango-extensionsプロジェクトを使用することをお勧めします。ただし、「shell_plus」管理コマンドの代わりに、次を使用します。

manage.py shell_plus --notebook

これにより、WebブラウザでIPythonノートブックが開きます。セルやインポートなどにコードを記述して実行します。

モジュールを変更するときは、ノートブックのメニュー項目「カーネル->再起動」をクリックするだけです。

これで、コードは変更されたモジュールを使用するようになりました。


30
「Pythonノートブックを使用するだけ」は、OPの質問に対する答えではありません。
j__ 2016

このメソッドは、%autoreloadのように自動ではありませんが、autoreloadよりも確実に機能します。カーネルの再起動により、ノートブック内のすべてのセルが完全にリロードされたモジュールを取得することが保証されます。さらに、必要に応じて、すべてのセルを再起動して実行できます。
アントンI.シポス2017年

72

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つの自動リロード戦略を使用して、一部のインポートが更新されないようにすることもできます。

%autoreload

  • すべてのモジュール(%aimportによって除外されたモジュールを除く)を自動的にリロードします。

%autoreload 0

  • 自動リロードを無効にします。

%autoreload 1

  • 入力したPythonコードを実行する前に、%aimportでインポートされたすべてのモジュールを毎回リロードします。

%autoreload 2

  • 入力したPythonコードを実行する前に、毎回すべてのモジュール(%aimportで除外されたモジュールを除く)をリロードします。

%aimport

  • 自動的にインポートされるモジュールまたはインポートされないモジュールを一覧表示します。

%aimport foo

  • モジュール 'foo'をインポートし、%autoreload1に対して自動リロードされるようにマークします。

%aimport -foo

  • モジュール 'foo'を自動リロードしないようにマークします。

これは一般的に私の使用には適していますが、いくつかの洞窟があります。

  • コードオブジェクトの置き換えは常に成功するとは限りません。クラスの@propertyを通常のメソッドに変更したり、メソッドをメンバー変数に変更したりすると、問題が発生する可能性があります(ただし、古いオブジェクトの場合のみ)。
  • 再ロードされる前にモジュールから(たとえば、モンキーパッチを介して)削除された関数はアップグレードされません。
  • C拡張モジュールはリロードできないため、自動リロードできません。

3
djangoを使用している場合/manage.py shell_plus...を入力%load_ext autoreloadしてから%autoreload 2、を入力すると、モデルが自動的に再読み込みされます。
Fusion

素晴らしい、あなたは私の日を作りました
Shamsul ArefinSajib19年

明らかに、これにはipythonをインストールする必要があることに注意してください。たとえば、stackoverflow.com
a / 47170195/50899

38

django-extensionsプロジェクトによって提供されるmanage.pyshell_plusコマンドを見てください。シェルの起動時にすべてのモデルファイルが読み込まれます。変更を自動リロードしますが、終了する必要はありません。そこで直接呼び出すことができます


40
shell_plusを使用していますが、モデルが自動再読み込みされていません。何かが足りませんか?
ディエゴポンチャーノ2014

30
shell_plusはモデルをリロードしないので、これは質問に答えません。
aljabear 2015

5
前述のように、shell_plusはモデルをリロードしません。
zenperttu 2015

2
何かが足りないかもしれませんが、shell_plusは何もリロードしません。起動時にすべてのモデルをロードするので便利ですが、それだけです。
マッドウォンバット2015

14
shell_plusは、自動再読み込みモジュールを使用してモジュールを再読み込みできます。「%load_extautoreload」と入力してから「%autoreload2」と入力します-ipython.org/ipython-doc/3/config/extensions/autoreload.htmlを
bbrame

37

それに対する私の解決策は、コードを記述してファイルに保存してから、以下を使用することです。

python manage.py shell <test.py

そのため、修正しようとしているものを修正するまで、変更を加え、保存して、そのコマンドを再度実行できます。


2
素晴らしくてシンプル。1つの注意点exit()として、pyファイルの最後に追加して、Djangoシェルをよりクリーンな方法で終了します。どうも。
マーク

シンプルでエレガントなソリューション。よくやった。
nikoskip

25

このトピックに関する一般的なコンセンサスは、python reload()が最悪であり、これを行うための良い方法がないということのようです。


不正解です。上記の@dongweimingの答えは解決策であり、最良の答えとして受け入れられるべきです。
ジョセフシーディ2015

3
彼の答えに対する複数のコメントは、shell_plusはモデルをリロードしないと言っています
Mad Wombat

1
自分でテストしたところ、リロードされません。また、手作業でインポートした非モデルコードはどうですか?
マッドウォンバット2015

私が使用しているアプリのクラスは、プレーンな非django-modelモジュールとその中のクラスを含めて、すばらしいリロード(Python 3.4.3、Django 1.9b1、django-extensions 1.5.9)になりました。この回答から5年が経ち、多くの開発が行われてきました。
ジョセフシーディ2015

1
40分前にセットアップで試しましたが、shell_plusは何もリロードしません。Django 1.7.10、python 3.4.3、django-extensions1.5.9。
マッドウォンバット2015


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では、「リロード」を使用してインポートする必要があります。

from importlib import reload

それが役に立てば幸い。もちろん、デバッグ用です。

乾杯。


2

ipython構成でshell_plusを使用します。これにより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_IMPORTSまたはSHELL_PLUS_POST_IMPORTSdocs)で定義されたものはすべて自動リロードされます!

pdb.set_trace()ファイルを保存するときにシェルがデバッガー(例)にある場合、リロードを妨げる可能性があることに注意してください。


1
答えてくれてありがとう。、私は2010年にそれを尋ねたことを私が知っていることをうれしく思いますけれどもあなたは注意かもしれません8年のオートリロードが最終的に:) shell_plusで動作した後、その
マッドウォンバット


0

正確にはあなたが望むものではありませんが、私は今、テストしたり物事をいじったりするための管理コマンドを自分で作成する傾向があります。

コマンドでは、ローカルの束を好きなように設定し、後でインタラクティブなシェルにドロップすることができます。

import code

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

リロードはありませんが、djangoの機能をインタラクティブにテストするための簡単で煩わしくない方法です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.