pudbを利用したPythonスクリプトのデバッグ

pudbについて

Pythonのデバッガといえば、謹製のpdbが第一候補にあげられます。

pdbの機能 本家サイト(http://docs.python.jp/2/library/pdb.html) から引用 〜
「 (条件付き)ブレークポイントの設定やソース行レベルでのシングルステップ実行、スタックフレームのインスペクション、ソースコードスティングおよびいかなるスタックフレームのコンテキストにおける任意のPythonコードの評価をサポートしています。」

pudbpdbCUI版と言っても良いくらいの機能を備えている上に、CUIによる使いやすいユーザインターフェイスを備えているのが特徴で、コードリーディングやデバッグに活用できる非常に有効なツールです。

pudbのインストール

pipを利用してpudbをインストールします。

$ pip install pudb
Downloading/unpacking pudb
  Downloading pudb-2014.1.tar.gz (46kB): 46kB downloaded
  Running setup.py egg_info for package pudb

Downloading/unpacking urwid>=1.1.1 (from pudb)
  Downloading urwid-1.2.1.tar.gz (578kB): 578kB downloaded
  Running setup.py egg_info for package urwid

    warning: no files found matching 'CHANGELOG'
Downloading/unpacking pygments>=1.0 (from pudb)
  Downloading Pygments-1.6.tar.gz (1.4MB): 1.4MB downloaded
  Running setup.py egg_info for package pygments

[...]

Successfully installed pudb urwid pygments
Cleaning up...

pudbを利用する

ここでは以下のサンプルプログラムを例にpudbの操作例を紹介します。

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import sys


class Foo(object):
    def __init__(self):
        pass

    def hello(self, name='stranger'):
        print 'Hello, %s!' % name


def usage():
    sys.stderr.write('Usage: hello.py <your name>\n')


def main():
    foo = Foo()
    try:
        foo.hello(sys.argv[1])
    except IndexError:
        usage()
        sys.exit(1)


if __name__ == '__main__':
    main()

##
## [EOF]
##

pudbコマンドラインオプション

pudbのコマンドラインオプションは以下の通りです。

$ pudb --help
Usage: pudb [options] SCRIPT-TO-RUN [SCRIPT-ARGUMENTS]

Options:
  -h, --help          show this help message and exit
  -s, --steal-output
  --pre-run=COMMAND   Run command before each program run

現在(2014/06/24)の時点で -sオプションはNotImplemented となっています。

$ pudb -s hello.py
Traceback (most recent call last):
  File "/Users/saitou/venv/test/bin/pudb", line 9, in <module>
    load_entry_point('pudb==2014.1', 'console_scripts', 'pudb')()
  File "/Users/saitou/venv/test/lib/python2.7/site-packages/pudb/run.py", line 30, in main
    steal_output=options.steal_output)
  File "/Users/saitou/venv/test/lib/python2.7/site-packages/pudb/__init__.py", line 48, in runscript
    dbg = _get_debugger(steal_output=steal_output)
  File "/Users/saitou/venv/test/lib/python2.7/site-packages/pudb/__init__.py", line 35, in _get_debugger
    dbg = Debugger(**kwargs)
  File "/Users/saitou/venv/test/lib/python2.7/site-packages/pudb/debugger.py", line 155, in __init__
    raise NotImplementedError("output stealing")
NotImplementedError: output stealing

pudbを起動する直前に実行するコマンドがあれば --pre-run に指定します。
例えば、lsコマンドを実行したければ --pre-run=/bin/ls のような書式で指定します。

pudbを起動する

pudbは2通りの方法で利用できます。

a) pudbコマンドで起動する

引数にfooを与えてhello.pyを起動します。

$ pudb hello.py foo

b) -m pudbpythonのオプションとして指定する

$ python -m pudb hello.py foo

初期設定(Ctrl+p)を行う

最初にpudbを起動すると設定画面からスタートします。[Ctrl+p]で随時設定画面を呼び出せます。設定項目は以下の通りです。 f:id:pyde:20140624144714p:plain

主な設定項目

  • Line Numbers:
  • [x]にした場合は、コードの行番号表示を行う
  • Prompt on quit:
  • [x]にした場合は、デバッグ対象スクリプトの実行完了後にpudbに処理を戻す
  • Shell:
  • [!]キーで切り替えるPythonシェルを選択する。カレントシェルに切り替わるclassicがオススメ。
  • Theme:
  • CUIのテーマ(見た目)を選択する
  • Changing this setting requires a restart of PuDB.
  • [x] rawを選択しておくと設定変更が即時反映する(ようにみえる)

ヘルプの表示(?)を行う

[?]キーでpudbのヘルプ機能を利用できる。

ヘルプ画面に表示されるpudbのキー操作は以下のとおり

Keys:
   Ctrl-p - edit preferences

   n - step over ("next")
   s - step into
   c - continue
   r/f - finish current function
   t - run to cursor
   e - show traceback [post-mortem or in exception state]

   H - move to current line (bottom of stack)
   u - move up one stack frame
   d - move down one stack frame

   o - show console/output screen

   b - toggle breakpoint
   m - open module

   j/k - up/down
   Ctrl-u/d - page up/down
   h/l - scroll left/right

   g/G - start/end
   L - show (file/line) location / go to line
   / - search
   ,/. - search next/previous

   V - focus variables
   S - focus stack
   B - focus breakpoint list
   C - focus code

   f1/?/H - show this help screen
   q - quit

   Ctrl-c - when in continue mode, break back to PuDB

   Ctrl-l - redraw screen

Command line-related:
   ! - invoke configured python command line in current environment
   Ctrl-x - toggle inline command line focus

   +/- - grow/shrink inline command line (active in command line history)
   _/= - minimize/maximize inline command line (active in command line history)

   Ctrl-v - insert newline
   Ctrl-n/p - browse command line history
   Tab - yes, there is (simple) tab completion

Sidebar-related (active in sidebar):
   +/- - grow/shrink sidebar
   _/= - minimize/maximize sidebar
   [/] - grow/shrink relative size of active sidebar box

Keys in variables list:
   \ - expand/collapse
   t/r/s/c - show type/repr/str/custom for this variable
   h - toggle highlighting
   @ - toggle repetition at top
   * - toggle private members
   w - toggle line wrapping
   n/insert - add new watch expression
   enter - edit options (also to delete)

Keys in stack list:
   enter - jump to frame

Keys in breakpoints view:
   enter - edit breakpoint
   d - delete breakpoint
   e - enable/disable breakpoint

pudbを操作する

pdbと同様に以下のように操作を行う。 変数の値はVariables:ペインに、ステップ実行中のスタック情報はStack:ペインに、設定したブレイクポイントの場所はBreakpoints:ペインにそれぞれ表示されます。

-nキーでステップオーバー -sキーでステップイン -bキーでブレイクポイントの設定 -VキーでVariables:ペインに移動 -SキーでStack:ペインに移動 -BキーでBreakpoints:ペインに移動 -Cキーでメインとなるコードペインに移動 -qでpudbを終了する

pudb操作画面

f:id:pyde:20140624144839p:plain

コマンドラインpythonコードを実行する

ステップ実行中にCommand line:ペインのPythonシェルから任意のPythonコードを実行可能です。 実行後に[clear]->[Ctrl+x]でコードペインに戻れます。

  • 例 print文で変数の値を表示 f:id:pyde:20140624144922p:plain

  • 例 Fooクラスのhello()メソッドを呼び出す f:id:pyde:20140624144952p:plain

pudbを終了する

設定でPrompt on quitがチェック[x]されている場合は、終了時にメニューが表示されて、再度実行(Restart)を選択することが可能です。 f:id:pyde:20140624144714p:plain

まとめ

pudbはpdbとほぼ同等の機能を有しています。Command line:ペインの操作の安定性に若干問題がありますが、それを補って余りあるユーザビリティを誇っています。これまでpdbを利用してきた方は一度試してみてください。非常に使いやすくデバッグ作業の効率化に貢献してくれる素敵なツールです。