私が読んだことから、Pythonでコードをデバッグするには2つの方法があります:
pdb
やipdb
などの従来のデバッガーを使用します。これは、c
のcontinue
、step-over
のn
、step-into
のs
などのコマンドをサポートしていますが、オブジェクト検査に非常に役立つIPythonシェルに直接アクセスすることはできません。
IPython by embedding を使用して、コードでIPythonシェルを使用します。 from ipython import embed
を実行してから、コードでembed()
を使用できます。プログラム/スクリプトがembed()
ステートメントにヒットすると、IPython Shellにドロップされます。これにより、すべてのIPythonの利点を使用して、オブジェクトの完全な検査とPythonコードのテストが可能になります。ただし、embed()
を使用する場合は、便利なキーボードショートカットを使用してコードでstep-by-stepを使用することはできません。
両方の長所を組み合わせる方法はありますか?つまり.
このタイプの「強化されたデバッグ」の例は、MATLABで見つけることができます。ここで、ユーザーalwaysは、MATLABエンジン/シェルへの完全なアクセス権を持ち、引き続きstep-by-step彼女のコードを通じて、条件付きブレークポイントを定義します。他のユーザーと議論したことから、これは、MATLABからIPythonに移行するときに最も見逃してしまうデバッグ機能です。
質問をあまり具体的にしたくはありませんが、私は主にEmacsで働いているので、この機能を取り入れる方法はないのでしょうか。 理想的、Emacs(またはエディター)を使用すると、プログラマーはコードの任意の場所にブレークポイントを設定し、インタープリターまたはデバッガーと通信して、選択した場所で停止し、完全なIPythonにすることができますその場所の通訳。
IPythonの%pdb
フラグについてはまだ誰も言及していません。 IPythonで%pdb
を呼び出すだけで、エラーが発生すると、自動的にipdb
にドロップされます。すぐにステップを踏むことはできませんが、その後はipdb
に入ります。
%load
を使用してファイルをロードし、関数を実行するだけで、個々の関数のデバッグが簡単になります。正しい位置にassert
を指定すると、エラーを強制することができます。
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ツールキット に基づいているため、プロジェクトで同じことを簡単に得ることができます。
Emacsの誰にとっても、 このスレッド は、OP
ipdb
を含む)で動作できます。isend-mode
。これら2つのパッケージの組み合わせは非常に強力であり、OPで説明されている動作を正確に再現し、さらに多くのことを行うことができます。
wiki記事 Realdb for ipdbの詳細。
このスレッドで言及されているすべてを含め、Pythonをデバッグするためのさまざまな方法を試した後、IPythonを使用してPythonをデバッグする好ましい方法の1つは、組み込みシェルを使用することです。
メソッド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)
を呼び出します。
呼び出し方に関係なく、インタープリターは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
を使用することです上記で作成しました。
pudb からIPythonセッションを開始し、必要に応じてデバッグセッションに戻ることができます。
ところで、ipdbは舞台裏でIPythonを使用しており、実際にTAB補完やマジックコマンド(1つは%
で始まる)などのIPython機能を使用できます。 ipdbで問題なければ、%run
や%debug
などのコマンドを使用してIPythonから起動できます。 ipdbセッションは、スタックトレースなどで上下に移動できるという意味で、実際のプレーンなIPythonセッションよりも優れています。「オブジェクトインスペクション」のipdbには何が欠けていますか。
また、Emacs> = 24.3にバンドルされているpython.elにはNice ipdbサポートがあります。
@gaborousの答えのアプローチのように見えます 非推奨 。
新しいアプローチは次のようです:
from IPython.core import debugger
debug = debugger.Pdb().set_trace
def buggy_method():
debug()
「!」の接頭辞pdbに入力するコマンドのシンボルは、IPythonシェルで何かをするのと同じ効果があるようです。これは、特定の機能や変数名のヘルプにアクセスするために機能します。たぶんこれはあなたをある程度助けるでしょう。例えば、
ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)
しかし、!help(numpy.transpose)は、numpy.transposeの予想されるヘルプページを提供します。変数名についても同様に、変数lがある場合、pdbで「l」と入力するとコードが一覧表示されますが、!lはlの値を出力します。
このヒント を試しましたか?
または、さらに良いことに、ipythonを使用して呼び出します:
from IPython.Debugger import Tracer; debug_here = Tracer()
その後、あなただけを使用することができます
debug_here()
ブレークポイントを設定するときはいつでも
1つのオプションは、 Spyder のようなIDEを使用することです。これにより、デバッグ中にコードを操作できるようになります(実際にはIPythonコンソールを使用)。実際、Spyderは非常にMATLABに似ていますが、これは意図的なものと思われます。これには、変数インスペクター、変数編集、ドキュメントへの組み込みアクセスなどが含まれます。
質問に対する正しい、簡単、クール、正確な答えは、-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
Pyzo IDEには、OPが要求したのと同様の機能があります。デバッグモードで起動する必要はありません。 MATLABと同様に、コマンドはシェルで実行されます。ソースコード行にブレークポイントを設定すると、IDEが実行を停止し、通常のIPythonコマンドもデバッグおよび発行できます。
ただし、別のブレークポイントを設定しない限り、ステップインはうまく動作しません(まだ?).
それでも、MATLABからは、これが私が見つけた最良のソリューションのようです。
Embed()コンソールでexit()と入力すると、コードは続行し、次のembed()行に進みます。
EmacsのIPython-Shellとpdb.set_trace()を介して設定されたブレークポイントから実行する必要があります。
Python-mode.el、M-x ipython RETなどで確認.
python 3.2からは、interact
コマンドがあります。これにより、完全なpython/ipythonコマンドスペースにアクセスできます。
これまで明示的には言われていませんが、IPython.embed()
を内部からipdb
から呼び出すことができます。
ipdb
は、コードのステップ実行や内省に適していますが、複数行などの他の処理は行いません。 IPythonは複数行のステートメントを適切に処理します。
デバッガーを誘導するには、コードで次を呼び出します。
import idpb; ipdb.set_trace()
これにより、イントロスペクションとステップ実行が可能になります。
IPython機能が必要な場合は、ipdb>
で次を呼び出します。
from IPython import embed; embed()
Emacsについては、ここで私の特異な解決策を紹介します。
M-x Shell
でEmacsを使用しています。 yassnippet
にipdb
が定義されており、これがデバッガーを誘導します。 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がインストールされている場合)。