IPythonを使用した段階的なデバッグ


170

私が読んだことから、Pythonでコードをデバッグする方法は2つあります。

  • pdbまたはなどの従来のデバッガーを使用しますipdb。これは、cfor continuenfor step-oversfor step-intoなどのコマンドをサポートしていますが、オブジェクトの検査に非常に役立つIPythonシェルに直接アクセスすることはできません。

  • IPythonシェルをコードに埋め込むことによるIPythonの使用 。あなたがすることができ、あなたのコードで使用します。プログラム/スクリプトがステートメントにヒットすると、IPythonシェルに移動します。これにより、すべてのIPythonの利点を使用して、オブジェクトの完全な検査とPythonコードのテストが可能になります。ただし、使用する場合、便利なキーボードショートカットを使用してコードをステップバイステップで実行することはできなくなります。from ipython import embedembed()embed()embed()

両方の長所を組み合わせる方法はありますか?すなわち

  1. できるように ステップバイステップの便利なPDB / ipdbキーボードショートカットを使用してコードによる。
  2. そのような手順(たとえば、所定のステートメント)で、本格的なIPythonシェルにアクセスできます。

デバッグIPython のように MATLAB:

このタイプの「拡張デバッグ」の例は、MATLABにあり、ユーザーは常に MATLABエンジン/シェルに完全にアクセスでき、コードを段階的に実行したり、条件付きブレークポイントを定義したりできます。他のユーザーと話し合ったところ、これは、MATLABからIPythonに移行するときに人々が最も見逃してしまうデバッグ機能です。

Emacsおよびその他のエディターでのIPythonデバッグ:

私は質問を具体的にしすぎたくありませんが、私は主にEmacsで作業しているので、この機能をそれに組み込む方法はあるのでしょうか。理想的には、Emacs(またはエディター)を使用すると、プログラマーはコードの任意の場所にブレークポイントを設定し、インタープリターまたはデバッガーと通信して、選択した場所で停止し、その場所で完全なIPythonインタープリターを使用できます。


pdbには!、ブレークポイントで任意のpythonコマンドを実行するコマンドがあります
Dmitry Galchinsky

5
私もMatlabに似たpythonデバッガーを探しています!たとえば、Pythonシェルで多くのプロトタイピングを行います。すべての変数はシェルで保存されます。今、私は問題に会います。シェルで計算された変数を使用して、1つの小さなコードをデバッグしたいと思います。ただし、新しいデバッガーは古い変数にアクセスできません。試作には不向きです。
user1914692 2013年

1
Emacsユーザーにとって、RealGUDは非常に優れたインターフェースを備えています。
クレメント2016年

1
@Clémentに感謝します。先月はリポジトリをフォローしてきましたが、プロジェクトに非常に興奮しています:)まだ試していません。要求されたものを達成する方法を示します。その他の参考のために、URLはgithub.com/rocky/emacs-dbgrです
Amelio Vazquez-Reina

@Clémentまた、RealGUDとipdbの経験がある場合は、github.com / rocky / emacs-dbgr / issues / 96で説明されている方法で試してみました。
Amelio Vazquez-Reina 2016

回答:


61

IPythonの%pdb魔法を使用できます。%pdbIPythonを呼び出すだけで、エラーが発生すると、自動的にに移動しipdbます。あなたはすぐに足を踏み入れるわけではありませんが、あなたはipdbその後にいます。

これにより、ファイルをロードし%loadて関数を実行するだけなので、個々の関数のデバッグが簡単になります。あなたassertは正しい位置にあるエラーを強制することができます。

%pdbラインマジックです。それを呼び出して%pdb on%pdb 1%pdb offまたは%pdb 0。引数なしで呼び出された場合は、トグルとして機能します。


6
^これは本当の答えは
セザール

最初にIPythonに含まれていなくても、pdbにIPythonのような機能がある場合、同様の何かがありますか?
Lucas

4
また、プログラムを起動しipython --pdb file.py -- argsて、例外発生時にipdbにドロップすることもできます。答えに追加する価値があるかもしれません。
セバスチャン

110

ipdb.set_trace()はどうですか?あなたのコードで:

import ipdb; ipdb.set_trace()

更新:Python 3.7では、次のように記述できますbreakpoint()。同じように機能しますが、PYTHONBREAKPOINT環境変数にも従います。この機能は、このPEPに由来しています。

これにより、コードの完全な検査が可能になり、c(続行)、n(次の行を実行)、s(ポイントでメソッドにステップイン)などのコマンドにアクセスできます。

ipdb repoコマンドのリストを参照してください。IPythonJupyterと呼ばれるようになりました(編集:の一部)。


PS:ipdbコマンドはPythonコードよりも優先されることに注意してください。だから書くにはlist(foo)あなたが必要になるでしょうprint list(foo)

また、ipythonプロンプト(そのemacsモードとvimモード、履歴、完了など)が気に入った場合は、pythonプロンプトツールキットに基づいているため、プロジェクトで同じように簡単に取得できます


10
これがその方法です。
j08lue

私の答えにはipdb、Emacsでの使用方法RealGUDisend-mode、OPの要求を正確に実行する方法が含まれています。
Amelio Vazquez-Reina

1
JupyterはIPythonの代わりではなく、IPython Notebookの代わりです。Jupyterノートブックはバックグラウンドでカーネルを使用します。Pythonノートブックの場合、カーネルは通常IPythonカーネルです。IPythonプロジェクトはさらに続きます。
FA

1
breakpoint()素晴らしいです。PyCharmでは、それはあなたをPyCharmデバッガに落とし込みさえします。これは、コンソールに貼り付けられた関数からPyCharmデバッガーに入る簡単な方法でもあります。
RichardMöhnDec

40

(2016年5月28日更新)EmacsでRealGUDを使用する

Emacsの誰にとっても、このスレッドは、OPで説明されているすべて(およびそれ以上)を使用して、

  1. RealGUDと呼ばれるEmacsの新しい重要なデバッガーipdb
  2. Emacsパッケージisend-mode

これら2つのパッケージの組み合わせは非常に強力で、OPで説明されている動作を正確に再現し、さらに多くのことを実行できます。

RealGUD for ipdbのwiki記事に関する詳細情報。


元の答え:

このスレッドで言及されているすべてを含む、Pythonをデバッグするためのさまざまな方法を試した後、IPythonでPythonをデバッグするための私の好ましい方法の1つは、組み込みシェルを使用することです。

カスタム埋め込みIPythonシェルの定義:

スクリプトに以下を追加しPYTHONPATHて、メソッドをipsh()使用できるようにします。

import inspect

# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config

# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = '   .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '

# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")   
exit_msg = '**Leaving Nested interpreter'

# Wrap it in a function that gives me more context:
def ipsh():
    ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)

    frame = inspect.currentframe().f_back
    msg   = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)

    # Go back one level! 
    # This is needed because the call to ipshell is inside the function ipsh()
    ipshell(msg,stack_depth=2)

次に、コード内の何かをデバッグしたいときはいつでも、ipsh()オブジェクト検査などを実行する必要がある場所に直接配置します。たとえば、my_function以下でデバッグしたいとします

それを使う:

def my_function(b):
  a = b
  ipsh() # <- This will embed a full-fledged IPython interpreter
  a = 4

次にmy_function(2)、次のいずれかの方法で呼び出します。

  1. この関数をUnixシェルから呼び出すPythonプログラムを実行する
  2. または、IPythonから直接呼び出す

どのように呼び出すかに関わらず、インタープリターはと言う行で停止しますipsh()。完了したら、実行することができCtrl-D、Pythonが実行を再開します(行った変数の更新がある場合)。通常のIPython IPythonシェル(上記のケース2)からコードを実行する場合、新しいIPythonシェルは、呼び出し元のシェル内にネストされます。これは問題ありませんが、注意してください。どちらにしても、インタプリタがの場所で停止しipshたら、a(のいずれか2)の値を検査したり、定義されている関数やオブジェクトを確認したりできます。

問題:

上記のソリューションを使用すると、Pythonをコード内の任意の場所で停止し、本格的なIPythonインタープリターにドロップできます。残念ながら、スクリプトを起動した後はブレークポイントを追加または削除できません。これは非常にイライラします。私の意見では、これがIPythonがPythonの優れたデバッグツールになるのを妨げている唯一のものです。

今のところできる最善のこと:

回避策はipsh()、PythonインタープリターがIPythonシェル(つまりbreakpoint)を起動する別の場所にアプリオリを配置することです。次に、で事前定義されたハードコードされたさまざまな「ブレークポイント」間を「ジャンプ」できます。Ctrl-Dこれにより、現在の埋め込みIPythonシェルが終了し、インタープリターがへの次の呼び出しにヒットするたびに再び停止しipsh()ます。

このルートを使用する場合、「デバッグモード」を終了して後続のすべてのブレークポイントを無視する1つの方法ipshell.dummy_mode = Trueは、Python ipshellが上記で作成したオブジェクトの後続のインスタンス化をすべて無視するようにすることです。


2
さらに良い解決策を見つけたら、これを更新してください。しかし、これは素晴らしいですね。使用します。
Phani 2014年

1
どこで/どのようにcfg、banner_msg、exit_msgを定義/インポートし、検査しますか?
Gordon Bean

1
これは私にとってはうまくいくようです:github.com/kdodia/snippets/blob/master/ipsh.py
karan.dodia '18

1
機能するimport inspect前に追加する必要がありました。コマンドラインのカスタマイズは私にとっては壊れているようです。
Pascal

7
なぜ単に使用しないのimport ipdb; ipdb.set_trace()ですか?多分私は何かを逃しますが、私はあなたのはるかに複雑な方法の利点を見ていません。
Luator、2015

19

pudbからIPythonセッションを開始し、必要に応じてデバッグセッションに戻ることができます。

ところで、ipdbは舞台裏でIPythonを使用しており、TAB補完やマジッ​​クコマンド(で始まるもの%)などのIPython機能を実際に使用できます。ipdbで問題がなければ、%runやなどのコマンドを使用してIPythonから起動できます%debug。ipdbセッションは、スタックトレースなどで上下に移動できるという意味で、実際のIPythonセッションよりも優れています。「オブジェクト検査」のためにipdbに欠けているものは何ですか。

また、Emacs> = 24.3にバンドルされているpython.elは、素晴らしいipdbサポートを備えています。


1
ありがとうtkf。私はあなたのEmacs-Jediパッケージの大ファンです。Emacs 24.3がipdbをサポートしていると言ったとき、詳しく説明してもらえますか 通常はIPythonを別のM-x ansi-termバッファーで開始し、次にisend-modeを使用してソースバッファーをIPythonバッファーにバインドします。これにより、%pasteマジックをIPythonバッファーに自動的に送信するキーボードショートカットを使用して、IPythonインタープリターにコードを送信できます。これにより、IPythonで領域をすばやくテストできます。私はいつもこのIPythonシェルからプログラムを実行し、停止にrun使用embed()しています。
Amelio Vazquez-Reina

3
たとえば、コードをステップ実行すると、現在の実行ポイントを指す矢印を使用して、ソースコードが別のバッファで開かれます。isend-modeの場合と同様に、send-regionコマンドもあります。
tkf 2013年

ありがとう@tkf 対応するシェルipdbを使用python.elしてデバッグセッションを開始したりsend-region、そのようなものを使用するにはどうすればよいですか?一般に、これに関する詳細情報はどこにありますか?
Amelio Vazquez-Reina

%runまたはを使用します%debug。私import ipdb; ipdb.set_trace()もうまくいくと思います。ipdbに複数の行を送ることはできないと思います。これはipdbの制限です。しかし、おそらく%pasteトリックは機能します。IPython開発者に機能リクエストを送信することができます。
tkf 2013年


6

接頭辞「!」pdbに入力するコマンドへのシンボルは、IPythonシェルで何かを行うのと同じ効果があるようです。これは、特定の関数や変数名のヘルプにアクセスするために機能します。多分これはある程度あなたを助けるでしょう。例えば、

ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)

ただし、!help(numpy.transpose)を使用すると、numpy.transposeに関する予想されるヘルプページが表示されます。同様に、変数名の場合、変数lがあるとすると、pdbに「l」と入力するとコードがリストされますが、!lはlの値を出力します。


2
これは厄介なpdbの落とし穴であり、知っておく価値があります。
Wilfred Hughes

4

このヒントを試しましたか?

あるいは、ipythonを使用して、次のように呼び出します。

from IPython.Debugger import Tracer; debug_here = Tracer()

その後、あなたはただ使うことができます

debug_here()

ブレークポイントを設定したいときはいつでも


4

IPython 内から 始められますipdb

ipdbデバッガー1を誘導します。

import idpb; ipdb.set_trace()

IPythonを入力内からipdb>コンソール2

from IPython import embed; embed()

ipdb>内からコンソールに戻りますIPython

exit

Emacsを使用できる運が良ければ、さらに便利になります。

これにはを使用する必要がありM-x shellます。使用するyasnippet、BM、次のスニペットを定義します。これipdbにより、エディター内のテキストが行に置き換えられますset-trace。スニペットを挿入すると、その行が強調表示され、簡単に見やすく、ナビゲートしやすくなります。M-x bm-nextナビゲートに使用します。

# -*- mode: snippet -*-
# name: ipdb
# key: ipdb
# expand-env: ((yas-after-exit-snippet-hook #'bm-toggle))
# --
import ipdb; ipdb.set_trace()

1簡単に削除できるように、1行にまとめています。imports一度だけ発生するので、このフォームはipdb余分なオーバーヘッドなしで必要なときにインポートされることを保証します。

2 ファイルIPython 内に.pdbrcインポートすることで、入力を節約できます

try:
    from IPython import embed
except:
    pass

これによりembed()、内部から簡単に呼び出すことができますipdb(もちろん、IPythonがインストールされている場合のみ)。


3

1つのオプションは、SpyderのようなIDEを使用することです。これにより、デバッグ中に(実際にはIPythonコンソールを使用して)コードを操作できます。実際、Spyderは、MATLABに非常によく似ています。これには、変数インスペクター、変数編集、ドキュメントへの組み込みアクセスなどが含まれます。


3

質問に対する正しい、簡単、クール、正確な答えは、-dフラグを指定して%runマクロを使用することです。

In [4]: run -d myscript.py
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.        
> /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>()
      2                                                            
      3                        
----> 4 a=1                                            
      5 b=2

これはもっと高いはずです。(モジュール内の)コードに行を挿入する必要がある場合は、IPythonを再起動してモジュールをリロードする必要があります。これ%save /tmp/foo.py x-yを使用すると、実行してデバッグするコードと、%run -d /tmp/foo.py好きな場所にブレークポイントを設定することができます。正解です。
ロミオバレンティン


2

Pyzo IDEはを求めOPと同様の機能を持っています。デバッグモードで起動する必要はありません。MATLABと同様に、コマンドはシェルで実行されます。一部のソースコード行にブレークポイントを設定すると、IDEはそこで実行を停止し、通常のIPythonコマンドをデバッグして発行することもできます。

ただし、別のブレークポイントを設定しない限り、ステップインは(まだ?)うまく機能しないようです(つまり、1行で停止してから別の関数にステップインします)。

それでも、MATLABからの場合、これは私が見つけた最良のソリューションのようです。


2

python 3.2以降、このinteractコマンドを使用すると、完全なpython / ipythonコマンドスペースにアクセスできます。


1

EmacsのIPythonシェル内から実行し、pdb.set_trace()を介して設定されたブレークポイントが機能するはずです。

python-mode.el、Mx ipython RETなどで確認。


1

新しいコードの開発

IPython内でのデバッグ

  1. Jupyter / IPythonセル実行を使用して実験の反復を高速化する
  2. %% debugを使用してステップスルー

セルの例:

%%debug
...: for n in range(4):
...:    n>2

既存のコードのデバッグ

デバッグ中のIPython

  1. 壊れた単体テストのデバッグ: pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
  2. :テストケースの外部デバッグbreakpoint()python -m ipdbなど
  3. IPython.embed()は、デバッガー内で必要なIPythonの完全な機能を提供します。

Pythonについての考え

私はOPに同意します。MATLABがPythonでうまくやっていることの多くは、Pythonにはまだありませんし、実際にはそうすべきです。たぶんいつか私はCPythonにささいなバグ修正以上のものを提供するでしょう。

https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68

参照デバッグを使用してIPythonでコマンドを実行することは可能ですか?

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