web-dev-qa-db-ja.com

IPythonによる段階的なデバッグ

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

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

  • IPython by embedding を使用して、コードでIPythonシェルを使用します。 from ipython import embedを実行してから、コードでembed()を使用できます。プログラム/スクリプトがembed()ステートメントにヒットすると、IPython Shellにドロップされます。これにより、すべてのIPythonの利点を使用して、オブジェクトの完全な検査とPythonコードのテストが可能になります。ただし、embed()を使用する場合は、便利なキーボードショートカットを使用してコードでstep-by-stepを使用することはできません。

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

  1. 便利なpdb/ipdbキーボードショートカットを使用してコードでstep-by-stepできるようにします。
  2. そのようなステップ(たとえば、特定のステートメント)で、本格的なIPython Shellにアクセスできます。

IPythonデバッグas asMATLAB:

このタイプの「強化されたデバッグ」の例は、MATLABで見つけることができます。ここで、ユーザーalwaysは、MATLABエンジン/シェルへの完全なアクセス権を持ち、引き続きstep-by-step彼女のコードを通じて、条件付きブレークポイントを定義します。他のユーザーと議論したことから、これは、MATLABからIPythonに移行するときに最も見逃してしまうデバッグ機能です。

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

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

151

IPythonの%pdbフラグについてはまだ誰も言及していません。 IPythonで%pdbを呼び出すだけで、エラーが発生すると、自動的にipdbにドロップされます。すぐにステップを踏むことはできませんが、その後はipdbに入ります。

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

32
sebastian

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

import ipdb; ipdb.set_trace()

update:Python 3.7では、breakpoint()を記述できます。動作は同じですが、PYTHONBREAKPOINT環境変数に従います。この機能は this PEP から来ています。

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

ipdb repo および コマンドのリスト を参照してください。 IPython が呼び出されました(編集:の一部) Jupyter


ps:ipdbコマンドはpythonコードよりも優先されることに注意してください。したがって、list(foo)を記述するには、print list(foo)が必要です。

また、ipythonプロンプト(emacsおよびvimモード、履歴、完了など)が好きな場合は、 python Promptツールキット に基づいているため、プロジェクトで同じことを簡単に得ることができます。

100
Ehvince

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

Emacsの誰にとっても、 このスレッド は、OP

  1. RealGUDと呼ばれるEmacsの新しい重要なデバッガーは、任意のデバッガー(ipdbを含む)で動作できます。
  2. Emacsパッケージisend-mode

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

wiki記事 Realdb for ipdbの詳細。


元の回答:

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

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

メソッドipsh()が使用可能になるように、次のスクリプトをPYTHONPATHに追加します。

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シェルはnestedの内部にあることに注意してくださいあなたはそれを呼び出しました。これはまったく問題ありませんが、知っておくと良いでしょう。いずれにしても、インタプリタがipshの位置で停止すると、aの値(2である)を調べ、定義されている関数とオブジェクトなどを確認できます。

問題:

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

今のところできること:

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

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

40

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

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

また、Emacs> = 24.3にバンドルされているpython.elにはNice ipdbサポートがあります。

19
tkf

@gaborousの答えのアプローチのように見えます 非推奨

新しいアプローチは次のようです:

from IPython.core import debugger
debug = debugger.Pdb().set_trace

def buggy_method():
    debug()
11
Elliot Larson

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

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

しかし、!help(numpy.transpose)は、numpy.transposeの予想されるヘルプページを提供します。変数名についても同様に、変数lがある場合、pdbで「l」と入力するとコードが一覧表示されますが、!lはlの値を出力します。

6
user1953384

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

または、さらに良いことに、ipythonを使用して呼び出します:

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

その後、あなただけを使用することができます

debug_here()

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

4
gaborous

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

3
user2423516

質問に対する正しい、簡単、クール、正確な答えは、-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
3
Ping

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

ただし、別のブレークポイントを設定しない限り、ステップインはうまく動作しません(まだ?).

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

2
user6715080

Embed()コンソールでexit()と入力すると、コードは続行し、次のembed()行に進みます。

2
TurinTurambar

EmacsのIPython-Shellとpdb.set_trace()を介して設定されたブレークポイントから実行する必要があります。

Python-mode.el、M-x ipython RETなどで確認.

1
Andreas Röhler

python 3.2からは、interactコマンドがあります。これにより、完全なpython/ipythonコマンドスペースにアクセスできます。

1
alpha_989

これまで明示的には言われていませんが、IPython.embed()を内部からipdbから呼び出すことができます。

ipdbは、コードのステップ実行や内省に適していますが、複数行などの他の処理は行いません。 IPythonは複数行のステートメントを適切に処理します。

デバッガーを誘導するには、コードで次を呼び出します。

import idpb; ipdb.set_trace()

これにより、イントロスペクションとステップ実行が可能になります。

IPython機能が必要な場合は、ipdb>で次を呼び出します。

from IPython import embed; embed()

Emacsについては、ここで私の特異な解決策を紹介します。

M-x ShellでEmacsを使用しています。 yassnippetipdbが定義されており、これがデバッガーを誘導します。 bm パッケージは行を強調表示するので、ソースコードから削除することを忘れないでください:

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

IPythonを.pdbrcファイルにインポートします。

try:
    from IPython import embed
except:
    pass

これにより、ipdbインスタンスからembed()を呼び出すことができます(IPythonがインストールされている場合)。

1
Lorem Ipsum