web-dev-qa-db-ja.com

各変数を指定せずにpdbでPythonをデバッグするときにすべての変数値を出力する方法は?

私はPythonスクリプトを使用してpdbをデバッグしており、マニュアルではp変数特定のポイントで指定された変数の値を印刷するコマンドですが、20個の変数のような多くの変数があり、それらすべての値を追跡したい場合はどうすればよいですか?それぞれを手動で指定する場合、次のスクリプトを例に取ります。

a = 1
b = 2
c = 3

Pdbでデバッグし、次のようにp a、b、cを使用してすべてを印刷できます。

$ python -m pdb test.py 
> /media/test.py(1)<module>()
-> a = 1
(Pdb) n
> /media/test.py(2)<module>()
-> b = 2
(Pdb) n
> /media/test.py(3)<module>()
(Pdb) n
--Return--
> /media/test.py(3)<module>()->None
-> c = 3
(Pdb) p a, b, c
(1, 2, 3)
(Pdb) 

ただし、各変数を手動で指定する必要があります。各変数を指定せずに、すべての変数を一度に出力する方法はありますか?

44
renatov

pdbはフル機能のpython Shellであるため、任意のコマンドを実行できます。

locals()およびglobals()は、スコープ内のすべての変数とその値を表示します。

値に関心がない場合は、dir()を使用できます。

Pythonで変数を宣言すると、必要に応じてローカル変数またはグローバル変数に配置され、定義した変数とスコープ内にある何かを別の理由で区別する方法はありません。

Dir()を使用する場合、関心のある変数はそのリストの最初または最後にある可能性があります。キー、値のペアを取得する場合

locals()のフィルタリングは次のようになります。

>>> x = 10
>>> y = 20
>>> {k: v for k,v in locals().iteritems() if '__' not in k and 'pdb' not in k}
{'y': 20, 'x': 10}

Locals()が本当に混乱している場合は、もう少し重いものが必要になります。 pythonpathのモジュールに次の関数を配置し、デバッグセッション中にインポートできます。

def debug_Nice(locals_dict, keys=[]):
    globals()['types'] = `__import__`('types')
    exclude_keys = ['copyright', 'credits', 'False', 
                    'True', 'None', 'Ellipsis', 'quit']
    exclude_valuetypes = [types.BuiltinFunctionType,
                          types.BuiltinMethodType,
                          types.ModuleType,
                          types.TypeType,
                          types.FunctionType]
    return {k: v for k,v in locals_dict.iteritems() if not
               (k in keys or
                k in exclude_keys or
                type(v) in exclude_valuetypes) and
               k[0] != '_'}

Pastebin にサンプルセッションを追加しました

これが失敗するケースがいくつかあります。また、型を渡すことができるように拡張することもできます。ただし、定義した変数以外のほとんどすべてをフィルタリングできるはずです。

dir()

最後の20個の値が必要な場合は、>>> p var1 var2 ... varnはあなたに与えるでしょう、そしてdir()[-20:]のようにdir()をスライスしたほうが良いでしょう、しかし変数と値の間の関係を簡単に見ることはできません。例:「barの前または後にfooを宣言しましたか?」

その関係を確認したい場合は、変数がdir()の最後にあると想定して、次のようなものを試すことができます。最初にある場合は、異なる方法でスライスできます。変数が連続していない場合、これはうまく機能しません。

>>> Zip(dir(), [eval(var) for var in dir()])[-4:]
[('a', 10), ('var', 'var'), ('x', 30), ('y', 50)]
62
munk

この複数の言語のリスト で与えられているとおり:

_a = 1
b = 1
n = 'value'
#dir() == ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'b', 'n']
for var in dir()[4:]:
    value_of_var = eval(var)
    print(value_of_var)
_

出力:

_1
1
'value'
_

それぞれのラベル付けは、var + " equals " + eval(var)の印刷と同じくらい簡単です。

「理想的な出力」は、_p a, b, ... , n, ..._を入力した結果とまったく同じです。

_vars = []
for var in dir()[4:-1]
    vars.append(var)
print(Tuple(vars))
_

出力は次のようになります。

_(1, 1, 'value')
_
1
OJFord