def zero_divide(x):
try:
return 42/x
except ZeroDivisionError:
print("error")
zero_divide(0)
def zero_divide2(x):
return 42/x
try:
zero_divide2(0)
zero_divide2(1)
except ZeroDivisionError:
print("Eroor")
zero_divide2(10)
#注意try 和except的位置
在函数里一旦跳到 except部分 上文中的try剩余部分将不会执行
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
- 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
- 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
- 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。
下面是简单的例子,它打开一个文件,在该文件中的内容写入内容,但文件没有写入权限,发生了异常:
#!/usr/bin/python # -*- coding: UTF-8 -*- try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close()
在执行代码前为了测试方便,我们可以先去掉 testfile 文件的写权限,命令如下:
chmod -w testfile
再执行以上代码:
$ python test.py Error: 没有找到文件或读取文件失败
使用except而不带任何异常类型
你可以不带任何异常类型使用except,如下实例:
try: 正常的操作 ...................... except: 发生异常,执行这块代码 ...................... else: 如果没有异常执行这块代码
以上方式try-except语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。
try-finally 语句
try-finally 语句无论是否发生异常都将执行最后的代码。
try: <语句> finally: <语句> #退出try时总会执行 raise
except Exception:
Exception是BaseException的子類別,可以捕捉除了系統例外以外的所有例外。上例可以藉由KeyboardInterrupt中斷迴圈。
在Python 3中,可以在except捕捉到例外後,將例外物件指定給變數。例如:
>>> try:
... raise IndexError('11')
... except IndexError as e:
... print(type(e), str(e))
...
<class 'IndexError'> 11
如果在except中使用raise而不接上任何物件,則表示將except比對到的例外實例再度丟出。例如:
>>> try:
... raise EOFError
... except EOFError:
... print('got it')
... raise
...
got it
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
EOFError
raise from語法,會將from後接上的例外實例,設定給被raise的例外實例之__cause__。例如:
>>> try:
... try:
... raise EOFError('XD')
... except EOFError as e:
... print(e.args)
... raise IndexError('Orz') from e
... except IndexError as e:
... print(e.args)
... print(e.__cause__.args)
...
('XD',)
('Orz',)
('XD',)
實際上,如果你在except中raise某個例外,則原except所比對到的例外,無論有無使用raise from,都會自動設定給__context__。例如:
>>> try:
... try:
... raise EOFError('XD')
... except EOFError as e:
... print(e.args)
... raise IndexError('Orz') from e
... except IndexError as e:
... print(e.args)
... print(e.__cause__.args)
... print(e.__context__.args)
...
('XD',)
('Orz',)
('XD',)
('XD',)
使用*args和**kwargs语法。其中,*args是可变的positional arguments列表,**kwargs是可变的keyword arguments列表。并且,*args必须位于**kwargs之前,因为positional arguments必须位于keyword arguments之前。
下面一个例子使用*kwargs, 同时包含一个必须的参数和*args列表:
def test_kwargs(first, *args, **kwargs): print 'Required argument: ', first for v in args: print 'Optional argument (*args): ', v for k, v in kwargs.items(): print 'Optional argument %s (*kwargs): %s' % (k, v) test_kwargs(1, 2, 3, 4, k1=5, k2=6) # results: # Required argument: 1 # Optional argument (*args): 2 # Optional argument (*args): 3 # Optional argument (*args): 4 # Optional argument k2 (*kwargs): 6 # Optional argument k1 (*kwargs): 5
*args和**kwargs语法不仅可以在函数定义中使用,同样可以在函数调用的时候使用。不同的是,如果说在函数定义的位置使用*args和**kwargs是一个将参数pack的过程,那么在函数调用的时候就是一个将参数unpack的过程了。下面使用一个例子来加深理解:
def test_args(first, second, third, fourth, fifth): print 'First argument: ', first print 'Second argument: ', second print 'Third argument: ', third print 'Fourth argument: ', fourth print 'Fifth argument: ', fifth # Use *args args = [1, 2, 3, 4, 5] test_args(*args) # results: # First argument: 1 # Second argument: 2 # Third argument: 3 # Fourth argument: 4 # Fifth argument: 5 # Use **kwargs kwargs = { 'first': 1, 'second': 2, 'third': 3, 'fourth': 4, 'fifth': 5 } test_args(**kwargs) # results: # First argument: 1 # Second argument: 2 # Third argument: 3 # Fourth argument: 4 # Fifth argument: 5
使用*args和**kwargs可以非常方便的定义函数,同时可以加强扩展性,以便日后的代码维护。
你定义(define)一个带parameters的函数: def addition(x,y): return (x+y) 这里的x,y就是parameters 当你 addition(3,4) 调用(call)这个函数时,3,4就是你传入的arguments
我们可以使用raise语句自己触发异常
raise语法格式如下:
raise [Exception [, args [, traceback]]]
语句中 Exception 是异常的类型(例如,NameError)参数标准异常中任一种,args 是自已提供的异常参数。
最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。
一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。
定义一个异常非常简单,如下所示:
def functionName( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行
注意:为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。
例如我们捕获以上异常,"except"语句如下所示:
try: 正常逻辑 except Exception,err: 触发自定义异常 else: 其余代码