异常
异常是指程序中的例外,违例情况。异常机制是指程序出现错误后,程序的处理方法。当出现错误后,程序的执行流程发生改变,程序的控制权转移到异常处理。
捕获异常
异常处理可以使开发人员能以优雅的方式处理错误。
try-except
Python使用try-except语句处理异常。语法如下:
try:
# write some code
# that might throw exception
except <ExceptionType>:
# Exception handler, alert the user
在try语句块中,我们写入可能会产生异常的代码,当异常发生时,try语句块中的代码会被忽略,转而进入except语句块中处理异常。例如:
try:
= open('somefile.txt', 'r')
f print(f.read())
f.close()except IOError:
print('file not found')
上述代码的执行流程如下:
- 先执行介于try和except之间的语句。
- 如果没有异常,则except语句块中的代码会被跳过。
- 如果文件不存在,则产生异常,在try语句块中的其他代码会被跳过。
- 当异常发生时,如果异常类型和except关键字后的异常名称匹配,就执行except分支中的代码。上述代码中只能处理IOError异常,如要处理其他类型的异常,还需要添加更多的except分支。
多个except
try声明可以有多个except分支,它还可以选择else和finally分支。语法如下:
try:
<body>
except <ExceptionType1>:
<handler1>
except <ExceptionTypeN>:
<handlerN>
except:
<handlerExcept>
else:
<process_else>
finally:
<process_finally>
except分支类似于elif。当异常发生时,将检查except分支是否和异常类型匹配。如果匹配,就执行对应except分支中的代码。在最后一个except分支中,异常类型是被忽略了的。如果异常发生,但没有匹配到最后一个except之前的分支,则最后的except分支中的代码会被执行。如果没有任何异常发生,则执行else语句中的代码。finally分支中的代码,无论是否有异常发生,都会被执行。例如:
try:
= eval(input("Enter two numbers, separated by a comma : "))
num1, num2 = num1 / num2
result print("Result is", result)
except ZeroDivisionError:
print("Division by zero is error !!")
except SyntaxError:
print("Comma is missing. Enter numbers separated by comma like this 1, 2")
except:
print("Wrong input")
else:
print("No exceptions")
finally:
print("This will execute no matter what")
eval()函数允许在Python程序内部运行Python代码,了解更多关于eval()的信息,请访问http://stackoverflow.com/questions/9383740/what-does-pythons-eval-do
自定义异常
使用关键字raise,可以在方法中自定义异常。语法为:
raise ExceptionClass("Your argument")
例如:
def enterage(age):
if age < 0:
raise ValueError("Only positive integers are allowed")
if age % 2 == 0:
print("age is even")
else:
print("age is odd")
try:
= int(input("Enter your age: "))
num
enterage(num)
except ValueError:
print("Only positive integers are allowed")
except:
print("something is wrong")
当用户输入的年龄小于0时,程序显示结果为:
only positive integers are allowed
with关键字
with
表达式其实是try-finally
的简写形式。但是又不是全相同。
try:=open('xxx')
f
except:print('fail to open')
-1)
exit(
try:
do something
except:
do something
finally: f.cLose()
虽然这段代码运行良好,但比较冗长。而使用with的话,能够减少冗长,还能自动处理上下文环境产生的异常。如下面代码:
"""
格式
with context [as var]:
pass
"""
其中的context
是一个表达式,返回的是一个对象,var
用来保存context
表达式返回的对象,可以有单个或者多个返回值。
with open('1.txt') as f:
print(f.read())
print(f.closed)
表达式open('1.txt')
返回是一个io.TextIOWrapper
类型的变量用f
接受到。在with
语句块中就可以使用这个变量操作文件。执行with
这个结构之后,f
会自动关闭。相当于自带了一个finally
。
但是with
本身并没有异常捕获的功能,但是如果发生了运行时异常,它照样可以关闭文件释放资源。
with 语句实质是上下文管理:
- 上下文管理协议。包含方法
__enter__()
和__exit_()
,支持该协议对象要实现这两个方法。 - 上下文管理器,定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。
- 进入上下文的时候执行
__enter__
方法,如果设置as var
语句,var
变量接受__enter__()
方法返回值 - 如果运行时发生了异常,就退出上下文管理器。调用管理器
__exit__
方法。