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

网络请求不可避免会遇上请求超时的情况,在 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

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

(0)

相关推荐

  • python socket 超时设置 errno 10054

    python socket.error: [Errno 10054] 远程主机强迫关闭了一个现有的连接.问题解决方案: 前几天使用python读取网页.因为对一个网站大量的使用urlopen操作,所以会被那个网站认定为攻击行为.有时就不再允许下载.导致urlopen()后,request.read()一直卡死在那里.最后会抛出errno 10054. 这个错误是connection reset by peer.也就是传说的远端主机重置了此连接.原因可能是socket超时时间过长:也可能是requ

  • python设定并获取socket超时时间的方法

    python写法 import socket def test_socket_timeout(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "Default socket timeout: %s" %s.gettimeout() s.settimeout(100) print "Current socket timeout: %s" %s.gettimeout() if __name__

  • 详解python中自定义超时异常的几种方法

    最近在项目中调用第三方接口时候,经常会出现请求超时的情况,或者参数的问题导致调用异代码异常.针对超时异常,查询了python 相关文档,没有并发现完善的包来根据用户自定义的时间来抛出超时异常的模块.所以自己干脆自己来实现一个自定义的超时异常.目前找到了两种方式来实现超时异常的功能(signal.alarm().threading实现超时异常) 方法1 thread + time 原理:将要调用的功能函数放入子线程,通过设定子线程的阻塞时间,超时则主线程并不会等待子线程的执行.主线程退出,子线程就

  • Python装饰器限制函数运行时间超时则退出执行

    实际项目中会涉及到需要对有些函数的响应时间做一些限制,如果超时就退出函数的执行,停止等待. 可以利用python中的装饰器实现对函数执行时间的控制. python装饰器简单来说可以在不改变某个函数内部实现和原来调用方式的前提下对该函数增加一些附件的功能,提供了对该函数功能的扩展. 方法一. 使用 signal # coding=utf-8 import signal import time def set_timeout(num, callback): def wrap(func): def h

  • python超时重新请求解决方案

    在应用中,有时候会 依赖第三方模块执行方法,比如调用某模块的上传下载,数据库查询等操作的时候,如果出现网络问题或其他问题,可能有超时重新请求的情况: 目前的解决方案有 1. 信号量,但不支持window: 2.多线程,但是 如果是大量的数据重复操作尝试,会出现线程管理混乱,开启上万个线程的问题: 3.结合采用 eventlet 和 retrying模块 (eventlet 原理尚需深入研究) 下面的方法实现:超过指定时间重新尝试某个方法 # -*- coding: utf-8 -*- impor

  • Python使用urllib模块的urlopen超时问题解决方法

    在新的公司开始上班,今天工作的主题内容是市场部门需要抓取一些论坛用户的邮箱,以便发送营销邮件. 于是用了一个python脚本来执行,前面抓了几个都没有什么问题,后来碰到一个论坛,在执行urlopen的地方总是提示超时,百度了一下,因为我使用的是urllib不是urllib2,所以无法直接在urlopen里面加timeout参数,只能是设置全局脚本的超时时间 首先: 复制代码 代码如下: import socket 然后: 复制代码 代码如下: socket.setdefaulttimeout(6

  • python爬虫之urllib,伪装,超时设置,异常处理的方法

    Urllib 1. Urllib.request.urlopen().read().decode() 返回一个二进制的对象,对这个对象进行read()操作,可以得到一个包含网页的二进制字符串,然后用decode()解码成html源码 2. urlretrieve() 将一个网页爬取到本地 3. urlclearup() 清除 urlretrieve()所产生的缓存 4. info() 返回一个httpMessage对象,表示远程服务器的头信息 5. getcode() 获取当前网页的状态码 20

  • Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)

    我们可以利用urllib来抓取远程的数据进行保存哦,以下是python3 抓取网页资源的多种方法,有需要的可以参考借鉴. 1.最简单 import urllib.request response = urllib.request.urlopen('http://python.org/') html = response.read() 2.使用 Request import urllib.request req = urllib.request.Request('http://python.org

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

    网络请求不可避免会遇上请求超时的情况,在 requests 中,如果不设置你的程序可能会永远失去响应. 超时又可分为连接超时和读取超时. 连接超时 连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是 connect() ),Request 等待的秒数. import time import requests url = 'http://www.google.com.hk' print(time.strftime('%Y-%m-%d %H:%M:%S')) try: html = re

  • 详解python requests中的post请求的参数问题

    问题:最新在爬取某站点的时候,发现在post请求当中,参数构造正确却获取不到数据,索性将post的参数urlencode之后放到post请求的url后面变成get请求,结果成功获取到数据,对此展开疑问. 1.http请求中Form Data和Request Playload的区别: Ajax post请求中常用的两种参数形式:form data 和 request payload get请求的时候,我们的参数直接反映在url里面,为key1=value1&key2=value2形式,如果是pos

  • 详解Python requests模块

    前言 虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 "HTTP for Humans",说明使用更简洁方便. Requests 继承了urllib2的所有特性.Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码. 开源地址:https://github.com/ke

  • 详解Python中Addict模块的使用方法

    目录 介绍 1.安装 2.用法 3.要牢记的事情 4.属性,如键.item等 5.默认值 6.转化为普通字典 7.计数 8.更新 9.Addict 是怎么来的 介绍 Addit 是一个Python模块,除了提供标准的字典语法外,Addit 生成的字典的值既可以使用属性来获取,也可以使用属性进行设置. 这意味着你不用再写这样的字典了: body = {     'query': {         'filtered': {             'query': {              

  • 详解Python传入参数的几种方法

    Python传入参数的方法有:位置参数.默认参数.可变参数.关键字参数.和命名关键字参数.以及各种参数调用的组合 写在前面 Python唯一支持的参数传递方式是『共享传参』(call by sharing) 多数面向对象语言都采用这一模式,包括Ruby.Smalltalk和Java(Java的引用类型是这样,基本类型按值传递) 共享传参是指函数的各个形式参数获得实参中各个引用的副本:也就是说,函数内部的形参是实参的别名(alias) 这种方案的结果是,函数可能会修改作为参数传入的可变对象,但是无

  • 详解python破解zip文件密码的方法

    1.单线程破解纯数字密码 注意: 不包括数字0开头的密码 import zipfile,time,sys start_time = time.time() def extract(): zfile = zipfile.ZipFile('IdonKnow.zip')#读取压缩包,如果用必要可以加上'r' for num in range(1,99999,1): try: pwd = str(num) zfile.extractall(path='.',pwd=pwd.encode('utf-8')

  • 详解Python图像处理库Pillow常用使用方法

    PIL(Python Image Library)是python的第三方图像处理库,但是由于其强大的功能与众多的使用人数,几乎已经被认为是python官方图像处理库了. 其官方主页为:PIL. PIL历史悠久,原来是只支持python2.x的版本的,后来出现了移植到python3的库pillow,pillow号称是friendly fork for PIL,其功能和PIL差不多,但是支持python3. PIL(Python Imaging Library)是Python一个强大方便的图像处理库

  • 详解python播放音频的三种方法

    第一种 使用pygame模块 pygame.mixer.init() pygame.mixer.music.load(self.wav_file) pygame.mixer.music.set_volume(0.5) pygame.mixer.music.play() 缺点:pygame模块播放音频时,有时候会产生失真,且无法通过修改播放器的频率来矫正音色. 第二种 使用pyqt5模块 from PyQt5 import QtMultimedia from PyQt5.QtCore import

  • 详解python发送各类邮件的主要方法

    python中email模块使得处理邮件变得比较简单,今天着重学习了一下发送邮件的具体做法,这里写写自己的的心得,也请高手给些指点. 一.相关模块介绍 发送邮件主要用到了smtplib和email两个模块,这里首先就两个模块进行一下简单的介绍: 1.smtplib模块 smtplib.SMTP([host[, port[, local_hostname[, timeout]]]]) SMTP类构造函数,表示与SMTP服务器之间的连接,通过这个连接可以向smtp服务器发送指令,执行相关操作(如:登

  • 详解Python的Django框架中Manager方法的使用

    在语句Book.objects.all()中,objects是一个特殊的属性,需要通过它查询数据库. 在第5章,我们只是简要地说这是模块的manager .现在是时候深入了解managers是什么和如何使用了. 总之,模块manager是一个对象,Django模块通过它进行数据库查询. 每个Django模块至少有一个manager,你可以创建自定义manager以定制数据库访问. 下面是你创建自定义manager的两个原因: 增加额外的manager方法,和/或修manager返回的初始Quer

随机推荐