Traceback (most recent call last): # 告诉我们这是错误的跟踪信息 File "err.py", line 11, in <module> # 调用main()出错,在代码文件err.py的第11行,但原因在第9行 main() File "err.py", line 9, in main # 调用bar('0')出错,在代码文件err.py的第9行,但原因在第6行 bar('0') File "err.py", line 6, in bar # 原因是return foo(s) * 2这个语句出错了但还不是最终原因 return foo(s) * 2 File "err.py", line 3, in foo # return 10 / int(s)这个语句出错了,这是错误产生的源头,因为下面打印了具体错误 return 10 / int(s) ZeroDivisionError: division by zero # 根据错误类型ZeroDivisionError,我们判断,int(s)本身并没有出错,但是int(s)返回0,在计算10 / 0时出错,至此,找到错误源头。
这就是异常栈,出错了向大佬提问时记得把完整异常栈附上.
记录错误
python内置的logging模块可以轻松记录错误信息,而且程序出错后会继续执行,正常退出.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import logging deffoo(s): return10 / int(s)
defbar(s): return foo(s) * 2
defmain(): try: bar('0') except Exception as e: logging.exception(e) # 捕获错误栈
main() print('END')
1 2 3 4 5 6 7 8 9 10 11
# 执行后输出如下 ERROR:root:division by zero Traceback (most recent call last): File "err_logging.py", line 13, in main bar('0') File "err_logging.py", line 9, in bar return foo(s) * 2 File "err_logging.py", line 6, in foo return 10 / int(s) ZeroDivisionError: division by zero END
defdivide(x, y): try: result = x / y return result except Exception as e: print(f"发生异常: {e}", file=sys.stderr) # 获取错误并输出到console的标准错误 logging.error(f"发生异常: {e}", exc_info=True) # 记录到日志文件 returnNone
(Pdb) l 1 # err.py 2 -> s = '0' 3 n = int(s) 4 print(10 / n)
输入n单步执行代码
1 2 3 4 5 6
(Pdb) n > /Users/michael/Github/learn-python3/samples/debug/err.py(3)<module>() -> n = int(s) (Pdb) n > /Users/michael/Github/learn-python3/samples/debug/err.py(4)<module>() -> print(10 / n)
任何时候输入p <变量名>来查看变量的值
1 2 3 4
(Pdb) p s '0' (Pdb) p n 0
q退出
pdb.set_trace()
1 2 3 4 5 6
import pdb
s = '0' n = int(s) pdb.set_trace() # 运行到这里会自动暂停 print(10 / n)
运行到pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者命令c继续
1 2 3 4 5 6 7 8 9 10
$ python err.py > /Users/michael/Github/learn-python3/samples/debug/err.py(7)<module>() -> print(10 / n) (Pdb) p n 0 (Pdb) c Traceback (most recent call last): File "err.py", line 7, in <module> print(10 / n) ZeroDivisionError: division by zero