《Python3网络爬虫开发实战》崔庆才著 个人学习笔记 3.1.2 处理异常
这篇文章适用于已经跟着书敲过一遍代码的初学者。
以下是我在学习过程中对书中知识点简单的总结,方便学完后更好复习,以及遇到的一些困惑和解答,欢迎大家提出质疑和个人见解。

小节总结

主要介绍error模块中的两个参数:URLError和HTTPError。

URLError

URLError有一个属性reason,可以返回错误原因。
这个错误原因来自哪里呢?
来自HTTP服务器、底层网络栈、操作系统,python的socket/SLL库等等整个网络中的一环,也就是说,错误原因非常多,没法枚举。reason属性只是原封不动的返回这个错误原因。

HTTPError

HTTPError有三个属性,分别是reason、code、headers,可以返回错误信息、状态码和请求头。如果你对这三个参数不熟悉,可以参考《图解HTTP》(人民邮电出版社 上页宣著),只需要从头到尾看一遍就可以明白。

URLError和HTTPError的关系

HTTPError是URLError的子类,即URLError是父亲,HTTPError是儿子。
重点是父类和子类不是包含关系,是一种继承关系。我们不需要完全理解,只要简单理解为URLError包含了HTTPError,可以说URLError囊括面很广,但是功能单一,于是HTTPError在URLError方面进行了扩展。例如URLError中只有reason属性,HTTPError不仅有reason属性,还有对于HTTP服务来说更具体的code和headers。如此我们引出书中的代码:

from urllib import request,error
#except从上到下遍历,找到符合条件的跳出,只会输出一个
try:
	response=request.urlopen('https://cuiqingcai.com/index.com')
except error.HTTPError as e:
	#sep='\n'让每个参数分行显示
 	print(e.code,e.reason,e.headers,sep='\n')
except error.URLError as e:
      print(e.reason)
else:
      print("Request Successfully") 

基于URLError和HTTPError的关系,在使用时就要先检查HTTPError的错误代码,如上述代码所示。如果条件置换,URLError在前,那么HTTPError将不会执行,遇到有关HTTP服务的错误,就只会执行URLError中reason的错误。
这就表明了URLError(父类)是一般的情况,HTTPError(子类)是一般情况再分化的特殊情况。

类和对象

书中有一句原话:有时候,reason 属性返回的不一定是字符串,也可能是一个对象。作者并未做具体阐释,我们很容易产生了困扰。什么时候发回字符串,什么时候返回对象,这个原因有很多种。作者要强调的是reason返回并不唯一,我们只要理清代码中类和对象的关系即可。代码(改动一点点)如下:

try:
    response=urllib.request.urlopen('https://www.baidu.com',timeout=0.01)
except urllib.error.URLError as e:
    print(type(e.reason))
    #type返回参数e.reason所属的类标识
    print(e.reason)
    #判断对象e.reason是否是指定类(或其任意子类)的实例
    if isinstance(e.reason,socket.timeout):
        print('TIME OUT')
输出:
<class 'TimeoutError'>
_ssl.c:1015: The handshake operation timed out
TIME OUT

我们首先了解,e.reason是对象,在代码中,socket.timeout是socket模块中一个异常类,而异常类的实例就是对象。socket.timeout是专门用来表示超时的原因,原因有很多种,不同的超时错误原因(连接超时、读取超时),是这个类的不同实例,也就是对象(实例和对象在大多数场景下都是等价的)。
于是我们就能理解,第一个输出语句中,输出的是对象的类;第二个输出语句中输出的是对象的字符串形式。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐