Python学习(十一)错误与异常
- Chapter 8 错误与异常
-
- 8.1 语法错误
-
- (1)拼写错误
- (2)不符合语法规范
- (3)缩进错误
- 8.2 异常的处理-`try-except`
-
- (1)ZeroDivisionError异常处理
- (2)FileNotFoundError异常处理
- (3)跨越多层调用
- (4)常见的异常及其处理
- 8.3 记录异常-`logging`
- 8.4 抛出异常
-
- (1)`raise`语句
- (2)`assert`语句
Chapter 8 错误与异常 8.1 语法错误 语法错误属于Python常见错误(Error)的一种。语法错误指的是程序的写法不符合编程语言规定。常见语法错误有:
(1)拼写错误
关键字、变量名、函数名拼写错误。关键字错误时会在运行时给出SyntaxError的提示,变量名、函数名拼写错误则提示NameError。
- 例:
>>> for i in range(3):
printt(i)
Traceback (most recent call last):
File "", line 2, in
printt(i)
NameError: name 'printt' is not defined
这里函数名
print
拼写错误写成printt
,给出了NameError的错误提示。(2)不符合语法规范
如缺少括号、冒号等符号,表达式书写错误。
- 例
>>> for i in range(3)
print(i)
SyntaxError: invalid syntax
缺少冒号,出现SyntaxError语法错误的提示。
(3)缩进错误
4个空格作为一个缩进,或用Tab实现。符合Python语法并方便阅读。
8.2 异常的处理-
try-except
异常(Exception) 指的是Python中的特殊对象,用于管理程序执行期间发生的错误。也就是错误发生时,Python会创建一个异常对象。若异常被处理,程序将继续运行;若没被处理,则停止程序并显示一个
traceback
,包含有关异常的报告。(1)ZeroDivisionError异常处理
异常的处理一般使用
try-except
代码块,执行指定操作。- 例:
>>> print(5/0)
Traceback (most recent call last):
File "", line 1, in
print(5/0)
ZeroDivisionError: division by zero
Traceback指出错误ZeroDivisionError是一个异常对象。下面使用
try-except
代码块进行处理:>>>
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
You can't divide by zero!
若
try
语句的部分出现异常,则执行except
语句的部分。可以要求用户提供有效输入,避免异常带来崩溃。将成功执行的代码放在
else
代码块中:print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
输出
Give me two numbers, and I'll divide them.
Enter 'q' to quit.First number: 5
Second number: 0
You can't divide by 0!First number: 5
Second number: 2
2.5First number: q
【Python|【Python】Python学习(十一)错误与异常】这样遇到异常,程序依然能够继续运行,用户也看不到traceback的内容。
(2)FileNotFoundError异常处理
找不到文件会引发FileNotFoundError异常。
- 例:
>>> file=open('eeee.txt','r')Traceback (most recent call last):
File "", line 1, in
file=open('eeee.txt','r')
FileNotFoundError: [Errno 2] No such file or directory: 'eeee.txt'
找不到名为
eeee.txt
的文件,采用try-except
代码块进行处理。用except...as...:
语句,将报错存储在变量中。- 输出错误
try:
file = open('eeee.txt','r')
except Exception as e:
print(e)
[Errno 2] No such file or directory: 'eeee.txt'
- 处理错误
try:
file = open('eeee.txt','r+')
except Exception as e:
print(e)
response = input('Do you want to create a new file?:')
if response == 'y':
file = open('eeee.txt','w')
else:
pass
else:
file.write('ssss')
file.close()
没找到文件,因此报错:
No such file or directory
;给出解决方法,输入y则新建一个文件(写入类型),否则不进行任何操作并跳出程序。再次运行后,文件已被找到,字符串ssss
被写入。(3)跨越多层调用
使用
try...except
代码块进行异常捕获的好处在于,它可以实现跨越多层调用。- 例:
- 定义
def foo(s):
return 10 / int(s)def bar(s):
return foo(s) * 2def main():
try:
bar('0')
except Exception as e:
print('Error:', e)
finally:
print('finally...')
- 调用
>>> main()
Error: division by zero
finally...
函数
main()
调用bar()
,bar()
调用foo()
,结果foo()
出错了,这时,只要main()
捕获到了,就可以处理。这样就不需要在每个可能出错的地方去捕获异常,只需在合适的层次进行异常捕获。如果异常未被捕获,则会沿着栈往上层抛出,直至被Python解析器捕获并打印错误信息,程序退出:
def foo(s):
return 10 / int(s)def bar(s):
return foo(s) * 2def main():
bar('0')main()
执行后结果如下:
Traceback (most recent call last):
File "err.py", line 11, in
main()
File "err.py", line 9, in main
bar('0')
File "err.py", line 6, in bar
return foo(s) * 2
File "err.py", line 3, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
层层分析调用栈信息,最后定位到错误的位置在
return 10 / int(s)
,产生了ZeroDivisionError
的异常。(4)常见的异常及其处理
常见的异常如下:
文章图片
Python的异常也属于类,所有异常类型都由
BaseException
类派生的。常见异常类型和继承关系可参考文档:https://docs.python.org/3/library/exceptions.html#exception-hierarchy
上文提到
except
的两种用法;
:只使用except
和使用except...as...
。主要用法如下:文章图片
可见
except
可以捕获所有异常或指定的异常。8.3 记录异常-
logging
Python内置的logging
模块可用于记录异常信息。- 例:
- 定义和调用
import loggingdef foo(s):
return 10 / int(s)def bar(s):
return foo(s) * 2def main():
try:
bar('0')
except Exception as e:
logging.exception(e)main()
print('END')
- 执行
ERROR:root:division by zero
Traceback (most recent call last):
File "err_logging.py", line 11, in main
bar('0')
File "err_logging.py", line 7, in bar
return foo(s) * 2
File "err_logging.py", line 4, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
END
异常信息打印后继续执行,程序可以正常退出。此外
logging
可以将错误记录到日志文件中。8.4 抛出异常 (1)
raise
语句上文提到的异常均是因错误引发的异常。错误Python提供
raise
语句来引发指定的异常,并向异常传递数据。每次执行语句,只能抛出一次异常。使用方式如下:raise [ExceptionName[(reason)]
三种用法:
①
raise
抛出上下文捕获的异常;②
raise 异常类名称
抛出指定类型的异常;③
raise异常类名称(描述信息)
:抛出指定类型的异常,并附带其描述信息。- 例1:
需要自定义一个异常类,选择好继承关系,再使用raise
语句抛出一次的实例。
class FooError(ValueError):
passdef foo(s):
n = int(s)
if n == 0:
raise FooError('invalid value: %s' % s)
return 10 / nfoo('0')
Traceback (most recent call last):
File "err_raise.py", line 10, in
foo('0')
File "err_raise.py", line 7, in foo
raise FooError('invalid value: %s' % s)
FooError: invalid value: 0
- 例2:
ValueError
,TypeError
)def foo(s):
n = int(s)
if n==0:
raise ValueError('invalid value: %s' % s)
return 10 / ndef bar():
try:
foo('0')
except ValueError as e:
print('ValueError!')
raisebar()
输出
ValueError!
Traceback (most recent call last):
File "err_reraise.py", line 14, in
bar()
File "err_reraise.py", line 9, in bar
foo('0')
File "err_reraise.py", line 4, in foo
raise ValueError('invalid value: %s' % s)
ValueError: invalid value: 0
这里
bar()
函数的raise
语句不带参数,将当前错误原样抛出。捕获异常的目的是记录,便于后续追踪。(2)
assert
语句assert
(断言)可以理解为raise
的简化。其用于判断一个表达式,在表达式条件为false的时候触发异常。条件不满足的时候直接返回错误。使用方法:
assert expression [, arguments]
- 例1:
>>> assert True
>>> assert False
Traceback (most recent call last):
File "", line 1, in
assert False
AssertionError
false时触发异常。
- 例2:
>>> def foo(s):
n = int(s)
assert n != 0,'n is zero!'
return 10 / n>>> foo('0')
Traceback (most recent call last):
File "", line 1, in
foo('0')
File "", line 3, in foo
assert n != 0,'n is zero!'
AssertionError: n is zero!
将
raise
语句的例子进行修改。这里assert
的意思是,表达式n != 0
是True,否则,断言失败,触发AssertionError
。通常
assert
语句用作测试代码的有效性,若不符合要求则触发异常,中断程序。要关闭程序中的assert
语句,启动Python解释器的-O
参数,则使用python -O
即可关闭。$ python -O err.py
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
====================================================================
Python学习的内容参考
《Python编程:从入门到实践》-[美] Eric Matthes
《21天学通PYTHON》
莫烦Python
廖雪峰的Python教程
等
推荐阅读
- Python开发笔记|[Python]Curl命令模拟与json解析
- 杂记|深大计网实验 4(Socket 网络编程)
- Python学习|Python学习-错误和异常的处理
- Python学习笔记|Python基础教程(异常处理)
- 看这一篇就够了!Python Openpyxl完整开发实例分析
- python|Kafka
- C语言与C++编程|马斯克(我是 Rust 粉丝,但为了性能会选择 C语言)
- 游戏|这就是传说中的天才程序员吧! | 每日趣闻
- 10个超级实用的Python自动化脚本