Python:捕获urllib.request超时异常(socket.timeout: timed out)


1. 背景

??在使用urllib.request.urlopen时,经常出现超时异常(socket.timeout: timed out)导致程序停止运行。每次停止还要重启程序,这不利于程序的健壮性。现希望捕获urllib的超时异常来做超时处理。

超时异常

2. 网上相关说法

??在网上搜索怎么捕获urllib超时异常,有的说无法捕获,有的说使用isinstance(e.reason, socket.timeout),故以此编写如下程序进行测试发现:isinstance(e.reason, socket.timeout)不能捕获超时异常,程序直接报错退出。这可能是因为python2与python3不同版本的urllib,本次测试使用的是python3.7。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from urllib import request, error
import socket


# 测试url是否有效
def test_url(url):
    try:
        pose_req = request.urlopen(url, timeout=0.1)  # 为检测超时异常,设timeout=0.1
        pose_data = pose_req.read().decode('utf-8')  # 读取请求结果
        print(pose_data[0:1000])
    except error.HTTPError as e:
        print(e.code + ':' + e.reason)
    except error.URLError as e:
        if isinstance(e.reason, socket.timeout):
            print('时间超时')
        else:
            print(e.reason)


if __name__ == '__main__':
    url1 = 'http://tieba.baidu.com/p/6353804665'
    test_url(url1)

运行报错

3. 个人实例

??学习python爬虫时,经常使用urllib发现HTTPError 和URLError 基本没怎么用到。而timed out频繁出现,故尝试使用“except Exception as e”捕获除与程序退出sys.exit()相关之外的所有异常,发现:“except Exception as e”可以捕获超时异常(socket.timeout: timed out)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from urllib import request, error
import socket


# 测试url是否有效
def test_url(url):
    try:
        pose_req = request.urlopen(url, timeout=0.1)  # 为检测超时异常,设timeout=0.1
        pose_data = pose_req.read().decode('utf-8')  # 读取请求结果
        print(pose_data[0:1000])
    except Exception as e:
        print(e)


if __name__ == '__main__':
    url1 = 'http://tieba.baidu.com/p/6353804665'
    test_url(url1)

捕获超时异常

4. 小结

  1. 使用“except Exception as e”捕获超时异常(socket.timeout: timed out);
  2. 新方法,新技术不一定有用,但经典的老办法总有一定的道理。