使用回溯查找错误
Python中的异常是语言的核心功能。
回溯
回溯几乎始终包含以下信息:
- 涉及对每个函数的每次调用的所有文件路径
- 与每个文件路径关联的行号
- 产生异常时涉及的函数、方法或类的名称
- 引发的异常的名称
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> open("/path/to/mars.jpg")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/path/to/mars.jpg'
>>>
处理异常
try和except块
如果文件或目录不存在,则会引发FileNotFoundError。如果想要处理此异常,可以使用try和except块。
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
... open('config.txt')
... except FileNotFoundError:
... print("Couldn't find the config.txt file!")
...
Couldn't find the config.txt file!
>>>
在 try
关键字之后,添加可能引发异常的代码。 接下来,添加 except
关键字与可能的异常,后跟在该条件发生时需要运行的任何代码。 由于 config.txt 在系统中不存在,因此 Python 将打印配置文件不存在。 try
和 except
块以及有用的消息会阻止回溯,并仍通知用户有关此问题的信息。
删除config.txt文件,创建一个文件config.txt,还是显示不了IsADirectoryError的错误信息。
无文件:
有文件:
IsADirectoryError,暂时没有机会遇到。
如果导航系统负载过大,并且文件系统变得太忙,则很有必要同时捕获 BlockingIOError 和 TimeOutError。
有文件:
无文件:
暂时没有机会遇到BlockingIOError和TimeoutError。
如果需要访问与异常相关的错误,则必须更新 except 行以包含 as 关键字。 如果异常太过普通,则这种方法就非常方便并且错误消息会很有用:
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
... open("mars.jpg")
... except FileNotFoundError as err:
... print("got a problem trying to read the file:",err)
...
got a problem trying to read the file: [Errno 2] No such file or directory: 'mars.jpg'
>>>
>>> try:
... open("mars.jpg")
... except OSError as err:
... if err.errno==2:
... print("Couldn't find the config.txt file!")
... elif err.errno==13:
... print("Found config.txt but couldn't read it")
...
Couldn't find the config.txt file!
>>>
处理错误时:
错误不指出真正的问题。
错误给出与实际问题不匹配的输出。
错误不指示可以执行哪些操作来解决问题。
引发异常
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> def water_left(astronauts,water_left,days_left):
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... return f"Total water left after {days_left} day is: {total_water_left} liters"
...
>>> water_left(5,100,2)
'Total water left after 2 day is: -10 liters'
>>> def water_left(astronauts,water_left,days_left):
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... if total_water_left<0:
... raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {day_left} days!")
... return f"Total water left after {day_left} days is: {total_water_left} liters"
...
>>> water_left(5,100,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in water_left
NameError: name 'day_left' is not defined. Did you mean: 'days_left'?
>>> try:
...
File "<stdin>", line 2
^
IndentationError: expected an indented block after 'try' statement on line 1
>>> def water_left(astronauts,water_left,days_left):
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... if total_water_left<0:
... raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {day_left} days!")
... return f"Total water left after {days_left} days is: {total_water_left} liters"
...
>>> water_left(5,100,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in water_left
NameError: name 'day_left' is not defined. Did you mean: 'days_left'?
>>> def water_left(astronauts,water_left,days_left):
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... if total_water_left<0:
... raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {days_left} days!")
... return f"Total water left after {days_left} days is: {total_water_left} liters"
...
>>> water_left(5,100,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in water_left
RuntimeError: There is not enough water for 5 astronauts after 2 days!
>>> def water_left(astronauts,water_left,days_left):
... for argument in[astronauts,water_left,day_left]:
... try:
... argument/10
... except TypeError:
... raise TypeError(f"All arguments must be of type int, but received: '{argument}'")
... daily_usage=astronauts*11
File "<stdin>", line 7
daily_usage=astronauts*11
^^^^^^^^^^^
SyntaxError: invalid syntax
>>> def water_left(astronauts,water_left,days_left):
... for argument in[astronauts,water_left,day_left]:
... try:
... argument/10
... except TypeError:
... raise TypeError(f"All arguments must be of type int, but received: '{argument}'")
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... if total_water_left<0:
... raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {after_left} days!")
... return f"Total water left after {days_left} days is: {total_water_left} liters"
...
>>> water_left("3","200",None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in water_left
NameError: name 'day_left' is not defined. Did you mean: 'days_left'?
>>> def water_left(astronauts,water_left,days_left):
... for argument in[astronauts,water_left,days_left]:
... try:
... argument/10
... except TypeError:
... raise TypeError(f"All arguments must be of type int, but received: '{argument}'")
... daily_usage=astronauts*11
... total_usage=daily_usage*days_left
... total_water_left=water_left-total_usage
... if total_water_left<0:
... raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {after_left} days!")
... return f"Total water left after {days_left} days is: {total_water_left} liters"
...
>>> water_left("3","200",None)
Traceback (most recent call last):
File "<stdin>", line 4, in water_left
TypeError: unsupported operand type(s) for /: 'str' and 'int'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in water_left
TypeError: All arguments must be of type int, but received: '3'
>>>