pythonasyncio异常处理_Python异常的处理记录参考资料来⾄:PythonCookbook
⾸先要知道,所有的异常事⼀个类。
如果⼀个单独的代码块处理所有不同的异常,可以将它们归组到⼀个元祖中。
import URLError
try:
<_url(url)
except (URLError, ValueError, SocketTimeout):
这个错误元祖(URLError, ValueError, SocketTimeout)捕获到都会执⾏ve_url(url)
如果对⼀个单独的采取不同的处理⽅法,可以将其放⼊⼀个单独的except中
try:
<_url(url)
except (URLError, ValueError):
except SocketTimeout:
有许多归组为继承体系,对于这样的异常,可以通过指定⼀个基类来捕获所有异常。
try:
f = open('a.txt')
except (FileNotFoundError, PermissionError):
...
try:
f = open('a.txt')
except OSError:
...
# 查下此类下⾯的⼦类
print(OSError.__subclasses__())
print()
# 查看继承表
print(FileNotFoundError.__mro__)
[, , , ,
, , , ,
, , , , ]
(, , , , )
书中不严谨的地⽅事,明显OSError包含的错误类型更加多。
我们还可以通过as e,这个e就是捕获到错误的实例,实例的话就应该有⼀堆属性,你也可以通过type(e)的⽅式查看e的类型,便于精准捕获。
其中的error属性可以捕获到错误的代码。
except向下执⾏捕获到合适的异常,下⾯的except就不会执⾏。
try:
f = open('a.txt')
except OSError as e:
print(dir(e))
print('OSError')
# 这个肯定不会执⾏,应该OSError是FileNotFoundError的⽗类,它把包含它的所有异常都捕获了
except FileNotFoundError:parse error怎么解决
print('FileNotFoundError')
下⾯上⼀下OSError对象的属性
['__cause__', '__class__', '__context__', '__delattr__', '__dict__',
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__',
'__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'characters_written', 'errno', 'filename', 'filename2',
'strerror', 'with_traceback']
捕获所有的异常
try:
...
# ⼀般错误这个够⽤了
except Exception as e:
...
# 这个是错误的祖宗
except BaseException as e:
...
除了SystemExit,KeyboardInterrupt,和GeneratorExit之外,Exception都能捕获,如果想前⾯⼏个异常也捕获可以⽤BaseException。
书中介绍说明,当我们捕获错误的时候,如果选择了Exception这样的⼴义错误,最好⽤as e,把e输出显⽰,这样再出现问题的时候,我们可以从实例e的输出中查看具体的情况。
创建⾃定义的异常
我们⽇常的使⽤中需要⼀些⾃⼰定义的异常,简单的操作,可以继承该类,并⾃⼰重新定义⼀个⾃⼰熟悉的类名。
实际操作中,我们⼀般总继承内奸的Exception类,或者继承⾃⼀些本地定义的基类,⽽这个基类本⾝⼜是继承⾃Exception的,不能去继承BaseException。
如果改写Exception的__init__⽅法,请确保所有参数传递给Exception的__init__,Exception默认的认为就是接收所有传递过来的参数,并将它以元祖的形式保存再args中。
In [82]: class My_Exception(Exception):
...: def __init__(self,message, status):
...: super().__init__(message, status)
...: ssage = message
...: self.status = status
...:
In [85]: try:
...: raise My_Exception('my error','888')
...: except My_Exception as e:
...: ssage)
...: print(e.status)
...: print(e.args)
...:
...:
...:
my error
888
('my error', '888')
通过引发异常来响应另⼀个异常。
要将异常串联起来,可以使⽤yield from。
In [94]: def example():
...: try:
...: int('n/a')
...: except ValueError as e:
...: raise RuntimeError('A parseing error occurred') from e
...:
In [95]: example()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in example()
----> 3 int('n/a')
4 except ValueError as e:
ValueError: invalid literal for int() with base 10: 'n/a'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
in
----> 1 example()
in example()
3 int('n/a')
4 except ValueError as e:
----> 5 raise RuntimeError('A parseing error occurred') from e
6
RuntimeError: A parseing error occurred
In [96]:
这⼀⾏是关键The above exception was the direct cause of the following exception:
在⽣成器throw(StopItoration)⾥⾯引起RuntimeError应该也是采⽤了yield from的⽅式。
In [97]: try:
...: example()
...: except RuntimeError as e:
...: print('It didnot work', e)
.
..: if e.__cause__:
...: print('Cause', e.__cause__,'type',type(e.__cause__))
...:
...:
It didnot work A parseing error occurred
Cause invalid literal for int() with base 10: 'n/a' type
我们可以从捕获的RuntimeError对象e⾥⾯发现有__cause__属性,调⽤后,为引起它错误的实例。In [98]: def example():
...: try:
...: int('n/a')
...: except ValueError:
...: raise RuntimeError('A parseing error occurred')
...:
In [99]: try:
...: example()
...: except RuntimeError as e:
...: print('It didnot work', e)
...: if e.__cause__:
...: print('Cause', e.__cause__,'type',type(e.__cause__))
...:
...:
It didnot work A parseing error occurred
In [100]: example()
-
--------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
in example()
2    try:
----> 3        int('n/a')
4    except ValueError:
ValueError: invalid literal for int() with base 10: 'n/a'
During handling of the above exception, another exception occurred:
RuntimeError                              Traceback (most recent call last)
in
----> 1 example()
in example()
3        int('n/a')
4    except ValueError:
----> 5        raise RuntimeError('A parseing error occurred')
6
7
RuntimeError: A parseing error occurred
上⾯去掉了yield from 可以发现两个错误没有因果关系,调⽤__cause__属性为空.
在except⾥⾯⽆论是否是raise还是raise from,该脚本的调⽤者,抓取异常以最后复现的异常为准。就像前⾯写的函数,最后抓取函数异常,只能通过RuntimeError抓取。
如果处于某种元婴想阻⽌异常链的发⽣,可以使⽤raise from None 完成
In [103]: example()