python请求模块和连接重用

时间:2014-07-21 20:18:14

标签: python keep-alive

我正在使用python的HTTP通信请求模块,我想知道如何重用已经建立的TCP连接?请求模块是无状态的,如果我反复调用get获取相同的URL,那么每次都会创建一个新连接吗?

谢谢!

2 个答案:

答案 0 :(得分:38)

requests.getrequests.post等全局函数会在每次调用时创建requests.Session实例。使用这些功能建立的连接无法重复使用,因为您无法访问自动创建的会话并使用它的连接池进行后续请求。如果你只需要做几个请求就可以使用这些功能。否则,您将自己想要管理会话。

以下是使用全局requests功能和会话时get行为的快速显示。

准备工作,与问题无关:

>>> import logging, requests, timeit
>>> logging.basicConfig(level=logging.DEBUG, format="%(message)s")

请参阅,每次拨打get时都会建立新连接:

>>> _ = requests.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org
>>> _ = requests.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org

但如果您为后续调用使用相同的会话,则会重用连接:

>>> session = requests.Session()
>>> _ = session.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org
>>> _ = session.get("https://www.wikipedia.org")
>>> _ = session.get("https://www.wikipedia.org")
>>> _ = session.get("https://www.wikipedia.org")

性能:

>>> timeit.timeit('_ = requests.get("https://www.wikipedia.org")', 'import requests', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
...
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
52.74904417991638
>>> timeit.timeit('_ = session.get("https://www.wikipedia.org")', 'import requests; session = requests.Session()', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
15.770191192626953

当您重用会话(以及会话的连接池)时,工作速度会快得多。

答案 1 :(得分:6)

  

请求模块是无状态的,如果我反复调用get获取相同的URL,那么每次都会创建一个新连接吗?

requests模块不是无状态的;它只是让你忽略状态并有效地使用全局单例状态,如果你选择这样做。*

它(或者更确切地说,是其中一个底层库,urllib3)维护一个由(主机名,端口)对键控的连接池,因此如果可以,它通常会神奇地重用连接。

正如the documentation所说:

  

好消息 - 多亏了urllib3,keep-alive是100%自动的   在一次会议中!您在会话中发出的任何请求都将是   自动重用适当的连接!

     

请注意,连接仅会释放回池中以供重用   一旦读完所有身体数据;一定要将stream设置为   False或阅读content对象的Response属性。

那么,"它是什么"意思?正如上面提供的文档所暗示的那样,如果您保持流式响应对象的存活,那么它们的连接显然无法重用。

此外,连接池实际上是一个有限的缓存,而不是无限的,所以如果你发送大量的连接并且其中两个连接到同一个服务器,你就不会总是重用连接,只需经常。但通常,这就是你真正想要的。


*此处相关的特定州是transport adapter。每个会话都有一个传输适配器。您可以手动指定适配器,也可以指定全局默认值,或者只使用默认的全局默认值,它基本上只包含urllib3.PoolManager来管理其HTTP连接。有关更多信息,请阅读文档。