python asyncio 异常处理_Python异常的处理记录

参考资料来至:PythonCookbook

首先要知道,所有的异常事一个类。

如果一个单独的代码块处理所有不同的异常,可以将它们归组到一个元祖中。

from urllib.error import URLError

try:

object.get_url(url)

except (URLError, ValueError, SocketTimeout):

object.remove_url(url)

这个错误元祖(URLError, ValueError, SocketTimeout)捕获到都会执行object.remove_url(url)

如果对一个单独的采取不同的处理方法,可以将其放入一个单独的except中

try:

object.get_url(url)

except (URLError, ValueError):

object.remove_url(url)

except SocketTimeout:

object.other_do(url)

有许多归组为继承体系,对于这样的异常,可以通过指定一个基类来捕获所有异常。

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:

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)

...: self.message = message

...: self.status = status

...:

In [85]: try:

...: raise My_Exception('my error','888')

...: except My_Exception as e:

...: print(e.message)

...: 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()

2 try:

----> 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()

---------------------------------------------------------------------------

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') from None

6

7

RuntimeError: A parseing error occurred

在设计代码的时候,如果需要再except中raise 错误,经量应该使用raise from,这样能够明确的表达处你希望引发第二个异常的意图。

少出现直接except下直接raise 下一个错误。

重新抛出上一个异常

我们在except块中捕获了一个异常,现在想将它重新抛出,可以再except中重新使用raise。

In [106]: def example():

...: try:

...: int('a')

...: except ValueError as e:

...: print(e)

...: raise

...:

In [107]: example()

invalid literal for int() with base 10: 'a'

---------------------------------------------------------------------------

ValueError Traceback (most recent call last)

in

----> 1 example()

in example()

1 def example():

2 try:

----> 3 int('a')

4 except ValueError as e:

5 print(e)

ValueError: invalid literal for int() with base 10: 'a'

这个以后再工作中,对异常进行采集还是非常有用的,采集了以后再次进行上浮报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值