簡體   English   中英

回溯后如何檢查變量?

[英]How to inspect variables after Traceback?

我的 Python 腳本崩潰了。 為了調試它,我以交互模式運行它python -i example.py

Traceback (most recent call last):
  File "example.py", line 5, in <module>
    main()
  File "example.py", line 3, in main
    message[20]
IndexError: string index out of range

此時,我想檢查變量message 我試過

>>> message
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'message' is not defined

message不在范圍內(盡管main是)。 這令人沮喪。 如何檢查變量? 是否有更有用的python -i版本可以在崩潰時保留范圍內的內容(而不是頂級)?


用於上面example.py代碼。 不用說,這是一種簡化。

def main():
    message = "hello world"
    message[20]

main()

僅在出現異常時才進入調試器,您可以定義自定義 exceptionhook

import sys
def excepthook(type_, value, tb):
    import traceback
    import pdb
    traceback.print_exception(type_, value, tb)
    pdb.post_mortem(tb)
sys.excepthook = excepthook

def main():
    message = "hello world"
    message[20]

main()

運行腳本會將您帶入 pdb 和引發異常的框架中:

% script.py
Traceback (most recent call last):
  File "/home/unutbu/pybin/script.py", line 16, in <module>
    main()
  File "/home/unutbu/pybin/script.py", line 14, in main
    message[20]
IndexError: string index out of range
> /home/unutbu/pybin/script.py(14)main()
-> message[20]
(Pdb) p message
'hello world'
(Pdb) p message[20]
*** IndexError: IndexError('string index out of range',)
(Pdb) p len(message)
11

如果定義 exceptionhook 看起來代碼太多,您可以將其隱藏在實用程序模塊中,例如 utils_debug.py:

import sys
def enable_pdb():
    def excepthook(type_, value, tb):
        import traceback
        import pdb
        traceback.print_exception(type_, value, tb)
        pdb.post_mortem(tb)
    sys.excepthook = excepthook

然后你只需要添加

import utils_debug as UDBG
UDBG.enable_pdb()

到您的script.py


或者,如果您使用的是IPython ,則可以使用%pdb 魔法函數(當出現異常時,它ipdb您放入ipdb )。


不清楚為什么在 pdb 提示符下檢查size會給你一個 NameError。 (可運行的示例非常有用。)您可以嘗試使用bt (回溯)來檢查幀堆棧。 如果size在與pdb當前所在的幀不同的幀中定義,則您可以使用u (up)轉到定義size的幀。

根據 Python 文檔https://docs.python.org/3.4/library/pdb.html

pdb.py也可以作為腳本調用來調試其他腳本。 例如: python -m pdb myscript.py 當作為腳本調用時,如果被調試的程序異常退出,pdb會自動進入事后調試。

這並不完全准確。 它實際上在第一行進入調試。

$ python -m pdb example.py
> example.py(1)<module>()
-> def main():

但是,如果您鍵入c它將繼續崩潰

(Pdb) c
Traceback (most recent call last):
  File "C:\Python34\lib\pdb.py", line 1661, in main
    pdb._runscript(mainpyfile)
  File "C:\Python34\lib\pdb.py", line 1542, in _runscript
    self.run(statement)
  File "C:\Python34\lib\bdb.py", line 431, in run
    exec(cmd, globals, locals)
  File "<string>", line 1, in <module>
  File "example.py", line 1, in <module>
    def main():
  File "example.py", line 3, in main
    message[20]
IndexError: string index out of range
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> example.py(3)main()

此時,您可以鍵入message來檢查變量。

-> message[20]
(Pdb) message
'hello world'

哇!

一個簡單的替代方法是使用cgitb模塊。

import cgitb; cgitb.enable(format='text')


def main():
    message = "hello world"
    message[20]

main()

現在回溯本身打印消息的值。

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 /home/anand/projects/python/ptb/tes.py in <module>()
    4 def main():
    5     message = "hello world"
    6     message[20]
    7 
    8 main()
main = <function main>

 /home/anand/projects/python/ptb/tes.py in main()
    4 def main():
    5     message = "hello world"
    6     message[20]
    7 
    8 main()
message = 'hello world'
IndexError: string index out of range

您可以使用其他答案中提到的一些Python 調試器,或者嘗試使用我的診斷庫,該庫將更詳細的回溯存儲為 HTML 文件:) 只需在cheaters.py文件旁邊創建名為log目錄並啟用異常掛鈎通過下面的行:

from diagnostics import exception_hook
exception_hook.enable()

我通常使用代碼模塊來處理這種類型的事情。 盡早捕獲異常並將所有內容轉儲到交互式控制台中。

try:
    # something that might throw an error
except Exception as e:
    import code
    l={}
    l['global_vars'] = globals()
    l['local_vars'] = locals()
    code.InteractiveConsole(locals=l).interact()

這將在異常處理程序中啟動一個 python REPL,引發的異常將在 local_vars['e'] 中,您將可以訪問調用 try 塊的范圍。 如果在其他庫中引發異常,您可以使用此異常處理程序修改其他庫的代碼,使用 PYTHONPATH 環境變量將 python 指向庫的修改版本,並將原始版本保留在原處。

對於這些情況,我強烈推薦 ipython 和 ipdb。

在 ipython shell 中,您鍵入

run example.py

當未處理的異常返回到 ipython shell 時,您鍵入

%debug

這將使您進入 ipdb,位於引發未處理異常的確切代碼行。 然后,您可以簡單地通過評估變量來檢查變量,就像在普通 python shell 中一樣。

我的回答類似於已經被接受的恐慌上校的回答。 這里的主要優勢是 ipython 和 ipdb。 我更喜歡這些工具的原因有很多,最突出的是它們啟用了變量名稱的制表符補全。 一旦您習慣了 Tab 補全,就很難沒有它,因為它可以讓您工作得更快。

使用 , pdb 調試每一行

import pdb; pdb.set_trace()

這會讓你在每一行之后休息,你可以跟蹤你的代碼

def main():
    import pdb; pdb.set_trace()
    message = "hello world"
    message[20]

main()

當 main() 被調用時,這個函數將開始工作,你可以跟蹤消息,你可以調試它

你的終端看起來像這樣

> /home/admin/dxservices/example.py(3)main()
-> message = "hello world"
(Pdb) 
> /home/admin/dxservices/example.py(4)main()
-> message[20]
(Pdb) n
 IndexError: 'string index out of range'  
 > /home/admin/dxservices/example.py(4)main()
-> message[20]

這取決於什么最適合你。 由於這個問題留下了一些解釋空間,這里有一些替代方案。

以編程方式訪問變量以在代碼中使用它們

使用inspect模塊

except ... as ...:
    x = inspect.trace()[-1][0].f_locals['x']

為調試目的傳遞某個變量值,比如記錄它

將該值添加到異常消息中。

raise ValueError("oops, x={}".format(x))

但是如果一些外部代碼引發,你就不能這樣做。 此外,它需要時間並且不太實用。

只需打印導致異常的變量

嘗試使用回溯變量pip install traceback-with-variables ),這是明信片

在此處輸入圖片說明

tbvaccine ,或Better -exceptions任何其他包

還有一個使用調試器的選項,比如python -m pdb 這僅允許打印調試運行的信息,對生產沒有幫助,而且需要很多時間。 所以我會說這個選項是最不可取的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM