详解Python requests 超时和重试的方法


Posted in Python onDecember 18, 2018

网络请求不可避免会遇上请求超时的情况,在 requests 中,如果不设置你的程序可能会永远失去响应。

超时又可分为连接超时和读取超时。

连接超时

连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是 connect() ),Request 等待的秒数。

import time
import requests

url = 'http://www.google.com.hk'

print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
  html = requests.get(url, timeout=5).text
  print('success')
except requests.exceptions.RequestException as e:
  print(e)

print(time.strftime('%Y-%m-%d %H:%M:%S'))

因为 google 被墙了,所以无法连接,错误信息显示 connect timeout(连接超时)。

2018-12-14 14:38:20
HTTPConnectionPool(host='www.google.com.hk', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000000047F80F0>, 'Connection to www.google.com.hk timed out. (connect timeout=5)'))
2018-12-14 14:38:25

就算不设置,也会有一个默认的连接超时时间(我测试了下,大概是21秒)。

读取超时

读取超时指的就是客户端等待服务器发送请求的时间。(特定地,它指的是客户端要等待服务器发送字节之间的时间。在 99.9% 的情况下这指的是服务器发送第一个字节之前的时间)。

简单的说,连接超时就是发起请求连接到连接建立之间的最大时长,读取超时就是连接成功开始到服务器返回响应之间等待的最大时长。

读取超时是没有默认值的,如果不设置,程序将一直处于等待状态。 我们的爬虫经常卡死又没有任何的报错信息,原因就在这里了。

如果你设置了一个单一的值作为 timeout,如下所示:

r = requests.get('https://github.com', timeout=5)

这一 timeout 值将会用作 connect 和 read 二者的 timeout。如果要分别制定,就传入一个元组:

r = requests.get('https://github.com', timeout=(3.05, 27))

黑板课爬虫闯关的第四关正好网站人为设置了一个15秒的响应等待时间,拿来做说明最好不过了。

import time
import requests

url_login = 'http://www.heibanke.com/accounts/login/?next=/lesson/crawler_ex03/'

session = requests.Session()
session.get(url_login)

token = session.cookies['csrftoken']
session.post(url_login, data={'csrfmiddlewaretoken': token, 'username': 'guliang21', 'password': '123qwe'})

print(time.strftime('%Y-%m-%d %H:%M:%S'))

url_pw = 'http://www.heibanke.com/lesson/crawler_ex03/pw_list/'
try:
  html = session.get(url_pw, timeout=(5, 10)).text
  print('success')
except requests.exceptions.RequestException as e:
  print(e)

print(time.strftime('%Y-%m-%d %H:%M:%S'))

错误信息中显示的是 read timeout(读取超时)。

2018-12-14 15:20:47
HTTPConnectionPool(host='www.heibanke.com', port=80): Read timed out. (read timeout=10)
2018-12-14 15:20:57

超时重试

一般超时我们不会立即返回,而会设置一个三次重连的机制。

def gethtml(url):
  i = 0
  while i < 3:
    try:
      html = requests.get(url, timeout=5).text
      return html
    except requests.exceptions.RequestException:
      i += 1

其实 requests 已经帮我们封装好了。(但是代码好像变多了…)

import time
import requests
from requests.adapters import HTTPAdapter

s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))

print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
  r = s.get('http://www.google.com.hk', timeout=5)
  return r.text
except requests.exceptions.RequestException as e:
  print(e)
print(time.strftime('%Y-%m-%d %H:%M:%S'))

max_retries 为最大重试次数,重试3次,加上最初的一次请求,一共是4次,所以上述代码运行耗时是20秒而不是15秒

2018-12-14 15:34:03
HTTPConnectionPool(host='www.google.com.hk', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x0000000013269630>, 'Connection to www.google.com.hk timed out. (connect timeout=5)'))
2018-12-14 15:34:23

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python测试驱动开发实例
Oct 08 Python
Python的Flask框架中@app.route的用法教程
Mar 31 Python
python实现计算倒数的方法
Jul 11 Python
详解Python3中的Sequence type的使用
Aug 01 Python
python机器学习理论与实战(五)支持向量机
Jan 19 Python
python如何查看微信消息撤回
Nov 27 Python
Python实现字典排序、按照list中字典的某个key排序的方法示例
Dec 18 Python
Python元组知识点总结
Feb 18 Python
python读写csv文件并增加行列的实例代码
Aug 01 Python
python爬虫 批量下载zabbix文档代码实例
Aug 21 Python
django-xadmin根据当前登录用户动态设置表单字段默认值方式
Mar 13 Python
简述python四种分词工具,盘点哪个更好用?
Apr 13 Python
解决新django中的path不能使用正则表达式的问题
Dec 18 #Python
python 获取url中的参数列表实例
Dec 18 #Python
python 函数内部修改外部变量的方法
Dec 18 #Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
Dec 18 #Python
python监测当前联网状态并连接的实例
Dec 18 #Python
Python实现繁体中文与简体中文相互转换的方法示例
Dec 18 #Python
解决python3 pika之连接断开的问题
Dec 18 #Python
You might like
PHP小技巧搜集,每个PHPer都来露一手
2007/01/02 PHP
PHP连接SQLSERVER 注意事项(附dll文件下载)
2012/06/28 PHP
PHP漏洞全解(详细介绍)
2012/11/13 PHP
PHP模板引擎Smarty的缓存使用总结
2014/04/24 PHP
CodeIgniter控制器之业务逻辑实例分析
2016/01/20 PHP
PHP如何将XML转成数组
2016/04/04 PHP
PHP与以太坊交互详解
2018/08/24 PHP
php实现登录页面的简单实例
2019/09/29 PHP
javascript 三种方法实现获得和设置以及移除元素属性
2013/03/20 Javascript
使用jQuery实现的网页版的个人简历(可换肤)
2013/04/19 Javascript
javascript函数重载解决方案分享
2014/02/19 Javascript
JavaScript对表格或元素按文本,数字或日期排序的方法
2015/05/26 Javascript
微信小程序实现多宫格抽奖活动
2020/04/15 Javascript
node中modules.exports与exports导出的区别
2018/06/08 Javascript
纯javascript前端实现base64图片下载(兼容IE10+)
2018/09/14 Javascript
Vue3新特性之在Composition API中使用CSS Modules
2020/07/13 Javascript
原生JavaScript实现拖动校验功能
2020/09/29 Javascript
[45:56]Ti4正赛第一天 VG vs NEWBEE 3
2014/07/19 DOTA
教你如何在Django 1.6中正确使用 Signal
2014/06/22 Python
在Django的URLconf中使用多个视图前缀的方法
2015/07/18 Python
Python的Tornado框架的异步任务与AsyncHTTPClient
2016/06/27 Python
解决Pycharm调用Turtle时 窗口一闪而过的问题
2019/02/16 Python
详解Python函数式编程—高阶函数
2019/03/29 Python
python3爬虫中异步协程的用法
2020/07/10 Python
德国宠物用品、宠物食品及水族馆网上商店:ZooRoyal
2017/07/09 全球购物
Prototype是怎么扩展DOM的
2014/10/01 面试题
计算机操作自荐信
2013/12/07 职场文书
公司投资建议书
2014/05/16 职场文书
个人工作总结范文2014
2014/11/07 职场文书
2014年减负工作总结
2014/12/10 职场文书
大专护理专业自荐信
2015/03/25 职场文书
初中班主任工作总结2015
2015/05/13 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
酒店工程部的岗位职责汇总大全
2019/10/23 职场文书
【HBU】数据库第四周 单表查询
2021/04/05 SQL Server
教你怎么用Python实现GIF动图的提取及合成
2021/06/15 Python