Files

179 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
doc_type: short
full_text: sources/03_Debugging.md
---
# 03_Debugging 总结
本文讲解 Python 程序崩溃后的基础调试方法,重点包括如何阅读 traceback、使用交互式解释器保留现场、用 `print()` 辅助排查,以及通过 Python 内置调试器 `pdb` 进行断点调试。
## 核心内容
### 1. 从 traceback 开始定位错误
当 Python 程序崩溃时,会输出 traceback,展示函数调用链和最终异常原因。
关键原则:
- traceback 的最后一行通常是崩溃的直接原因。
- 上方的 `File ... line ... in ...` 展示了调用栈,即程序如何一步步走到出错位置。
- 错误类型和错误信息非常重要,例如:
- `AttributeError: 'int' object has no attribute 'append'`
- 表示代码试图在整数对象上调用 `append()` 方法。
文中建议:如果 traceback 难以理解,可以把完整 traceback 粘贴到搜索引擎中查找相关解释。
相关概念:debugging、traceback、exceptions
## 2. 使用 `python3 -i` 保留崩溃现场
运行脚本时加上 `-i` 选项:
```bash
python3 -i blah.py
```
如果程序崩溃,Python 不会立即退出,而是进入交互式 REPL:
```python
>>>
```
这样可以在崩溃后继续检查解释器状态,例如:
- 查看变量值
- 调用函数
- 检查对象类型
- 复现局部问题
这种方式适合快速探索程序崩溃时的环境,是一种轻量级调试技巧。
相关概念:repl、debugging、runtime state
## 3. 使用 `print()` 调试
`print()` 调试是一种常见且实用的排查方式,通过在代码中输出变量和执行路径来理解程序行为。
本文特别强调:调试输出时应优先使用 `repr()`:
```python
def spam(x):
print('DEBUG:', repr(x))
```
原因是:
- `print(x)` 输出的是面向用户的友好显示。
- `repr(x)` 输出的是更精确、面向开发者的表示形式。
示例:
```python
>>> from decimal import Decimal
>>> x = Decimal('3.4')
>>> print(x)
3.4
>>> print(repr(x))
Decimal('3.4')
```
在调试中,`repr()` 能揭示对象的真实类型和构造形式,减少误判。
相关概念:print debugging、repr、debugging
## 4. 在程序中手动启动调试器
Python 3.7+ 可以使用内置函数 `breakpoint()` 在代码中设置调试入口:
```python
def some_function():
...
breakpoint()
...
```
程序执行到 `breakpoint()` 时会进入调试器,可以检查变量、单步执行、查看调用栈等。
旧版本 Python 中常见写法是:
```python
import pdb
pdb.set_trace()
```
`breakpoint()` 是现代推荐写法,而 `pdb.set_trace()` 仍会在旧教程或遗留代码中出现。
相关概念:pdb、breakpoints、debugging
## 5. 在调试器下运行整个程序
可以用 `pdb` 模块直接运行脚本:
```bash
python3 -m pdb someprogram.py
```
这样程序会在第一条语句前进入调试器,允许开发者提前设置断点、配置执行路径,并逐步观察程序运行。
常用 `pdb` 命令包括:
| 命令 | 作用 |
|---|---|
| `help` | 查看帮助 |
| `w` / `where` | 打印调用栈 |
| `d` / `down` | 向下移动一个栈帧 |
| `u` / `up` | 向上移动一个栈帧 |
| `b loc` / `break loc` | 设置断点 |
| `s` / `step` | 单步执行 |
| `c` / `continue` | 继续运行 |
| `l` / `list` | 列出源码 |
| `a` / `args` | 查看当前函数参数 |
| `!statement` | 执行 Python 语句 |
断点位置可以是:
```text
b 45 # 当前文件第 45 行
b file.py:45 # file.py 的第 45 行
b foo # 当前文件中的 foo() 函数
b module.foo # 某模块中的 foo() 函数
```
相关概念:pdb、breakpoints、call stack
## 练习
### Exercise 8.4: Bugs? What Bugs?
练习标题以玩笑方式强调:程序“能运行”并不代表没有 bug。调试是理解程序状态、定位异常和验证假设的重要过程。
## 关键收获
- traceback 是崩溃分析的第一入口,最后一行通常说明直接原因。
- `python3 -i script.py` 可以在脚本崩溃后保留交互式环境,方便检查状态。
- `print()` 调试简单有效,但输出调试信息时应优先使用 `repr()`。
- `breakpoint()` 是 Python 3.7+ 推荐的内置调试入口。
- `python3 -m pdb program.py` 可以从程序开始就进入调试器。
- `pdb` 支持调用栈查看、断点、单步执行、继续运行和动态执行语句等功能。
## 可延伸概念
- debugging:程序调试的一般策略与工具。
- traceback:Python 异常调用栈的阅读方法。
- pdb:Python 内置调试器的命令与工作流。
- repl:交互式解释器在调试中的用途。
- repr:对象精确表示与调试输出。
- breakpoints:断点在程序执行控制中的作用。
## Related Concepts
- [[concepts/调用栈与-traceback]]
- [[concepts/Python-pdb-调试器]]
- [[concepts/测试-日志与调试]]
- [[concepts/异常处理]]
- [[concepts/Python-交互式解释器]]
- [[concepts/课程练习工作流]]
- [[concepts/Python-开发环境]]
- [[concepts/断言]]
- [[concepts/Python-文档与帮助系统]]
- [[concepts/库接口设计]]