IPythonでサブモジュールをリロードする


363

現在、私はサブモジュールを含み、numpy / scipyを使用するpythonプロジェクトに取り組んでいます。Ipythonはインタラクティブコンソールとして使用されます。残念ながら、現在使用しているワークフローにはあまり満足していません。アドバイスをいただければ幸いです。

IPythonでは、フレームワークは単純なimportコマンドによってロードされます。ただし、多くの場合、フレームワークのサブモジュールの1つでコードを変更する必要があります。この時点でモデルは既にロードされており、IPythonを使用してモデルと対話します。

現在、フレームワークには相互に依存する多くのモジュールが含まれています。つまり、フレームワークが最初にロードされたとき、メインモジュールはサブモジュールをインポートして構成しています。コードの変更は、モジュールがを使用してリロードされた場合にのみ実行されますreload(main_mod.sub_mod)。フルパスを使用して、変更されたすべてのモジュールを個別にリロードする必要があるため、これは面倒です。reload(main_module)numpy / scipy。を再ロードせずに、すべてのサブモジュールも再ロードする場合は、非常に便利です。


もっと詳しく説明してもらえますか?However, it is often necessary to change code in one of the submodules of the framework.それはなぜnecessary to change codeですか?ありがとう
食べる

16
@eat:フレームワークは継続的に開発されているため、コードベースは常に変更されています。
アラン

回答:


531

IPythonには、いくつかの自動リロードマジックが付属しています

%load_ext autoreload
%autoreload 2

新しい行を実行する前に、変更されたすべてのモジュールを毎回リロードします。これが機能する方法は、と少し異なりdreloadます。いくつかの注意事項が適用されます%autoreload?。何が問題かを確認するために入力してください。


この設定を常に有効にする場合は、IPython構成ファイル~/.ipython/profile_default/ipython_config.py[1]を変更して追加します。

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

下記のコメントを介して@Kosへのクレジット。

[1]ファイルがない場合は、最初~/.ipython/profile_default/ipython_config.pyに呼び出す必要がありますipython profile create。または、ファイルはにあります$IPYTHONDIR


63
私が持っているc.InteractiveShellApp.extensions = ['autoreload']c.InteractiveShellApp.exec_lines = ['%autoreload 2']、私の中で~/.ipython/profile_default/ipython_config.py
Kos

4
ただし、これはパフォーマンスに影響を与える可能性があるため、注意して使用してください。
asmeurer 2013年

3
リロードは、IpythonシェルでEnterキーを押したときにのみ実行され、通常は目立ちません。
pv。

3
これはパッケージのデバッグ時にかなりうまく機能するので、dreloadの目的は何ですか?dreloadはあまりにも侵襲的で、matplotlibのようないくつかのパッケージがロードされたときにエラーを出力するようです。
ダッシュ1993年

3
@Kosメソッドを使用する場合は、cが定義されていることを確認してください。c = get_config()
Tickon

27

IPython 0.12(およびおそらくそれ以前)では、これを使用できます。

%load_ext autoreload
%autoreload 2

これは本質的にはpvによる回答と同じです。。ただし、拡張機能の名前が変更され、を使用してロードされるようになりました%load_ext


20

何らかの理由で、ノートブックから別のノートブックにコードインポートする場合、どちら%autoreloaddreloadこの状況では機能しません。プレーンなPythonのみが機能します。reload

reload(module)

[1]に基づく。


10
Python 3.4以降では、importlibモジュールでreloadを見つけることができます。この質問を参照してください。
Praveen

1
このメソッドは、%autoreloadテクニックとは異なり、インスタンスメソッドを追加するときに機能します。このためのサポートを追加するための未解決のバグレポート%autoreloadがあります。
ijoseph

18

IPythonはdreload()、すべてのサブモジュールを再帰的にリロードすることを提案しています。個人的には、私は%run()magicコマンドを使用することを好みます(ただし、John Salvatierがコメントで指摘したように、ディープリロードは実行しません)。


11
(残念ながら)%run script.pyは、呼び出すスクリプトではなく、呼び出すスクリプトのみをリロードすると思います。ビルドしているパッケージをデバッグしようとしている場合、これは苦痛になる可能性があります。
John Salvatier

2
NB。dreload最近のIPython(IPython 6.0など)では、deepreloadに置き換えられました。
dan mackinlay

8

importlib内部モジュールをインポートするためのアクセスを許可するという名前のモジュール。特に、それは機能を提供しますimportlib.reload()

import importlib
importlib.reload(my_module)

とは逆に%autoreloadimportlib.reload()モジュールに設定されているグローバル変数もリセットします。ほとんどの場合、それで十分です。

importlibPython 3.1以降でのみ使用できます。古いバージョンでは、moduleを使用する必要がありますimp


私のために働いた唯一の解決策
gustavz

5

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

それらの魔法の関数を何度も入力することを避けるために、それらをipython起動スクリプトに入れることができます(.ipython / profile_default / startupの下に.pyサフィックスを付けて名前を付けます。そのフォルダーの下のすべてのpythonスクリプトは字句順に読み込まれます)。次のようになります。

from IPython import get_ipython
ipython = get_ipython()

ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")

これは、たとえば%run script.pyIPython REPLからスクリプトを実行している場合にも機能するようです
Patrick Sanan

3

これはどう:

import inspect

# needs to be primed with an empty set for loaded
def recursively_reload_all_submodules(module, loaded=None):
    for name in dir(module):
        member = getattr(module, name)
        if inspect.ismodule(member) and member not in loaded:
            recursively_reload_all_submodules(member, loaded)
    loaded.add(module)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

これにより、指定したモジュールとサブモジュールのツリー全体が効果的にリロードされます。この関数を.ipythonrc(私はそう思う)に置くこともできるので、インタープリターを開始するたびにロードされます。


そのルックスの良い、しかし、それは使用してインポートされたモジュールのモジュールまたはメンバー覆っていない可能性がありますfrom ... import ...かをimport ... as。少なくとも、端末上でインタラクティブに作業するときに、しばしば問題が発生します。IPythonに保存されたマクロを使用して、事前定義された状態で作業を開始するために必要なインポートとセットアップを実行します。
Bernhard

これは、実際にカバーしfrom ... import ...そしてimport ... as限り、あなたは輸入ものがモジュールであるように。それがカバーしない唯一のものは、その__init__.pyファイルからロードされなかったパッケージ内のモジュールです。パッケージの場合、モジュールの__path__属性がディレクトリかどうかを確認できます。ある場合は、トラバースして、見つかったすべてのモジュールを再帰的にインポートします。著者がパッケージの解決策を求めていないため、この部分は記述しませんでした。
YH Wong

確かにこれはよさそうだ。私はこの可能性について考えました。同時に、これに基づいて、いくつかの組み込み機能があると予想しまし。しかし、これをどのように使うのか私には分かりませんでした。元の質問を投稿する前に発生していたはずの掘り下げの後で、この拡張機能を見つけました。
Alain

またpkgutil、パッケージがサブモジュールをトップモジュールにインポートしない場合でも、を使用してパッケージ内のすべてのサブモジュールを取得できます。stackoverflow.com/a/1707786/1243926
osa

また、次のことも行う必要がありますsys.modules:
。formodule

2

別のオプション:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

Ubuntu 14.04上のipythonおよびipython3 v5.1.0で検証済み。


1

リロードの標準的な方法は、を最初に開いた後に両方の方法を組み合わせることですIPython

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

これを行う前にモジュールをロードすると、たとえマニュアルを使用しても、それらは再ロードされませんreload(module_name)。まだ、非常にまれに、まだ調べていないクラスメソッドがリロードされないという不可解な問題が発生します。


1

上記autoreloadはIntelliJでのみ機能することに注意してください(ctrl + sまたはcmd + sを使用して)変更されたファイルを手動で保存する場合。自動保存では動作しないようです。


PyCharmについても同様です。
tsando

0

AnacondaのJupyter Notebooksでこれを行う:

%load_ext autoreload
%autoreload 2

メッセージを生成しました:

自動再読み込み拡張機能は既に読み込まれています。それをリロードするには、以下を使用します: %reload_ext autoreload

それを行うことが望ましいようです:

%reload_ext autoreload
%autoreload 2

バージョン情報:

ノートブックサーバーのバージョンは5.0.0で、次で実行されています:Python 3.6.2 | Anaconda、Inc. | (デフォルト、2017年9月20日13:35:58)[MSC v.1900 32ビット(Intel)]


0

これによってサブオブジェクトがリロードされることはありません。そのためにはIPythonのdeepreloadを使用する必要があると思います。

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