前面我们讲到的Python编程过程中,在可能出现异常的地方使用尝试语句,来正确的处理一些异常,可以保证程序不中断继续运行。

抛出异常
有时候,我们可能需要在程序的某些地方主动抛出异常,通知调用该代码的程序有错误发生这时候,我们就要用到。raise
语句。raise
语句就是帮助我们抛出知道异常的,比如:
In [6]: raise NameError("Bad Name")
-----------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-966a00c8f456> in <module>
----> 1 raise NameError("Bad Name")
NameError: Bad Name
raise
的使用很简单,它的语法如下:
raise [expression [from expression]]
如果它后面不带表达式(参数),它会重新引发当前作用域内最后一个激活的异常。如果当前作用域内没有激活的异常,将会引发RuntimeError来提示错误。
如果后面带有表达式,则将表达式求值为要抛出的异常对象,该表达式必须是一个异常实例或者是一个异常类(自继承BaseException
类)。如果它是一个异常类,它将通过调用没有参数的构造函数来隐式实例化:
raise NameError # 等同于 'raise NameError()'
raise
后面表达式还可以跟一个from
¸...。,用于异常的串联。from
子句的表达式必须是另一个异常或实例,它将作为可写的(可写入的)的__cause__
属性被关联到所引发的异常。如果引发的异常未被捕捉处理,两个异常都将被打印出来:
In [9]: try:
...: print(10/0)
...: except Exception as e:
...: raise RuntimeError("something is wrong") from e
...:
----------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-9-7de64aad634f> in <module>
1 try:
----> 2 print(10/0)
3 except Exception as e:
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-9-7de64aad634f> in <module>
2 print(10/0)
3 except Exception as e:
----> 4 raise RuntimeError("something is wrong") from e
5
RuntimeError: something is wrong
如果异常一个在except
[主语]或finally
[主语]中被抛出,类似的机制会隐式地发挥作用,的之前将异常关联被新到异常的__context__
属性例如:
In [10]: try:
...: print(10/0)
...: except:
...: raise RuntimeError("something is wrong")
...:
-----------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-10-e950a6292482> in <module>
1 try:
----> 2 print(10/0)
3 except:
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
RuntimeError Traceback (most recent call last)
<ipython-input-10-e950a6292482> in <module>
2 print(10/0)
3 except:
----> 4 raise RuntimeError("something is wrong")
5
RuntimeError: something is wrong
串连异常柯林斯通过在from
[主语]中用None
来显示地禁止:
In [11]: try:
...: print(10/0)
...: except:
...: raise RuntimeError("something is wrong") from None
...:
-------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-11-1818bd8b9d31> in <module>
2 print(10/0)
3 except:
----> 4 raise RuntimeError("something is wrong") from None
5
RuntimeError: something is wrong
用户自定义异常
Python的允许用户自定义异常类,应该通常直接或间接地继承自Exception
类。
自定义的异常类的名称通常以“错误”结尾,类似与内置标准异常的命名。自定义的异常类,可以像其它类那样可以执行任何操作,但通常保持简单,只提供用以处理程序为异常提取有关错误信息的属性为模块自定义多个不同错误的异常时,通常是为该模块定义一个异常基类,再为不同错误创建特定的子类例如。:
class ModuleError(Exception):
'''模块的异常基类'''
pass
class ModuleNameError(ModuleError):
'''模块的特定异常子类'''
pass
class ModuleValueError(ModuleError):
'''模块的另一个特定异常子类'''
pass
最后的清理操作:finally子句
finally
的英文[主语] try
语句的一个可选[主语],用于定义在任何情况下都执行的操作,叫做“清理操作”例如:
In [12]: try:
...: raise NameError
...: finally:
...: print('Bye :)')
...:
...:
Bye :)
-------------------------------
NameError Traceback (most recent call last)
<ipython-input-12-9cda1523ce81> in <module>
1 try:
----> 2 raise NameError
3 finally:
4 print('Bye :)')
5
NameError:
finally
子句总会在离开try
语句前被执行,无论发生异常与否。当在try
子句中发生了异常且尚未被except
子句处理(或者它发生在除或其他子句中)时,该异常将在终子句执行后被重新抛出。当try语句的任何其他子句通过break,continue或return语句离开时,最后也会在“离开之前”被执行,参考下面这个更复杂的例子:
In [13]: def divide(a, b):
...: try:
...: result = a / b
...: except ZeroDivisionError:
...: print('divided by zero!')
...: else:
...: print('result is', result)
...: finally:
...: print('leaving try')
...:
In [14]: divide(8, 2)
result is 4.0
leaving try
In [15]: divide(8, 0)
divided by zero!
leaving try
In [16]: divide('a', 2)
leaving try
-----------------------
TypeError Traceback (most recent call last)
<ipython-input-16-324d9fa22da2> in <module>
----> 1 divide('a', 2)
<ipython-input-13-5e4380c62566> in divide(a, b)
1 def divide(a, b):
2 try:
----> 3 result = a / b
4 except ZeroDivisionError:
5 print('divided by zero!')
TypeError: unsupported operand type(s) for /: 'str' and 'int'
从上面的例子我们看到,finally
子句总是会被执行。字符串但被除时引发了TypeError
的异常,异常这个没有被except
¸...。处理,在就会finally
¸...。执行后被重新抛出。
在编程实践中,finally
子句对释放文件或网络连接等外部资源是非常有用的。
总结
编程中,我们不仅要在恰当的地方处理异常,也要在必要的时候抛出异常,我们抛出异常时可以自定义异常。熟练运用异常可以使我们的程序更加健壮,别忘了必要的时候使用finally
来释放外部资源。
大家在学python的时候肯定会遇到很多难题,以及对于新技术的追求,这里推荐一下我们的Python学习扣qun:784758214,这里是python学习者聚集地!!同时,自己是一名高级python开发工程师,从基础的python脚本到web开发、爬虫、django、数据挖掘等,零基础到项目实战的资料都有整理。送给每一位python的小伙伴!每日分享一些学习的方法和需要注意的小细节

网友评论