翻譯:《實用的Python編程》08_03_Debugging

目錄 | 上一節 (8.2 日誌) | [下一節 (9 包)]()python

8.3 調試

調試建議

假設程序崩潰了:git

bash % python3 blah.py
Traceback (most recent call last):
  File "blah.py", line 13, in ?
    foo()
  File "blah.py", line 10, in foo
    bar()
  File "blah.py", line 7, in bar
    spam()
  File "blah.py", 4, in spam
    line x.append(3)
AttributeError: 'int' object has no attribute 'append'

那麼如今該怎麼辦呢?github

閱讀回溯信息

最後一行是程序崩潰的具體緣由:segmentfault

bash % python3 blah.py
Traceback (most recent call last):
  File "blah.py", line 13, in ?
    foo()
  File "blah.py", line 10, in foo
    bar()
  File "blah.py", line 7, in bar
    spam()
  File "blah.py", 4, in spam
    line x.append(3)
# Cause of the crash
AttributeError: 'int' object has no attribute 'append'

不過,回溯信息並不老是那麼易於閱讀或理解。bash

專業建議:將整個回溯粘貼到谷歌。app

使用交互式解釋器(REPL)

執行腳本的 時候,能夠使用選項 -i 使 Python 保持存活(keep alive)。函數

bash % python3 -i blah.py
Traceback (most recent call last):
  File "blah.py", line 13, in ?
    foo()
  File "blah.py", line 10, in foo
    bar()
  File "blah.py", line 7, in bar
    spam()
  File "blah.py", 4, in spam
    line x.append(3)
AttributeError: 'int' object has no attribute 'append'
>>>

選項 -i 能夠保留解釋器狀態。這意味着能夠在程序崩潰後查找錯誤信息。對變量的值和其它狀態進行檢查。spa

使用打印進行調試

使用 print() 函數進行調試很是常見。翻譯

建議:確保使用的是 repr() 函數debug

def spam(x):
    print('DEBUG:', repr(x))
    ...

repr() 函數顯示一個值的準確表示,而不是格式良好的輸出。

>>> from decimal import Decimal
>>> x = Decimal('3.4')
# NO `repr`
>>> print(x)
3.4
# WITH `repr`
>>> print(repr(x))
Decimal('3.4')
>>>

Python 的調試器

能夠在程序內手動啓動調試器(debugger)。

def some_function():
    ...
    breakpoint()      # Enter the debugger (Python 3.7+)
    ...

上述操做會在 breakpoint() 調用時啓動調試器。

在 Python 的早期版本中,可能會看到下面這樣的調試指南:

import pdb
...
pdb.set_trace()       # Instead of `breakpoint()`
...

(譯註:Python 3.7 以後,能夠使用內置函數 breakpoint() 代替 import pdb; pdb.set_trace()

在調試解釋器下運行程序

也能夠在調試器下運行整個程序:

bash % python3 -m pdb someprogram.py

上述操做會在第一行語句以前自動進入調試器,容許設置斷點和修改配置。

常見的調試器命令:

(Pdb) help            # Get help
(Pdb) w(here)         # Print stack trace
(Pdb) d(own)          # Move down one stack level
(Pdb) u(p)            # Move up one stack level
(Pdb) b(reak) loc     # Set a breakpoint
(Pdb) s(tep)          # Execute one instruction
(Pdb) c(ontinue)      # Continue execution
(Pdb) l(ist)          # List source code
(Pdb) a(rgs)          # Print args of current function
(Pdb) !statement      # Execute statement

斷點的位置能夠用下列任意一種方式進行表示:

(Pdb) b 45            # Line 45 in current file
(Pdb) b file.py:45    # Line 34 in file.py
(Pdb) b foo           # Function foo() in current file
(Pdb) b module.foo    # Function foo() in a module

練習

練習 8.4:Bugs? 什麼是 Bugs?

有 bug,咱們就解決 bug(It runs. Ship it!)。

目錄 | 上一節 (8.2 日誌) | [下一節 (9 包)]()

注:完整翻譯見 https://github.com/codists/practical-python-zh

相關文章
相關標籤/搜索