python请求模块和连接重用

python请求模块和连接重用,python,python-requests,keep-alive,Python,Python Requests,Keep Alive,我正在使用python的HTTP通信请求模块,我想知道如何重用已经建立的TCP连接?requests模块是无状态的,如果我重复调用同一个URL的get,它不会每次都创建一个新的连接吗 谢谢 请求模块是无状态的,如果我重复调用同一URL的get,它每次都不会创建一个新连接吗 请求模块不是无状态的;如果您选择这样做,它只允许您忽略状态并有效地使用全局单例状态* 而且它(或者,更确切地说,它是一个底层库,urllib3)维护一个由(主机名、端口)对键控的连接池,因此如果可以的话,它通常会神奇地重用一个

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

谢谢

请求模块是无状态的,如果我重复调用同一URL的get,它每次都不会创建一个新连接吗

请求
模块不是无状态的;如果您选择这样做,它只允许您忽略状态并有效地使用全局单例状态*

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

正如上面所说:

好消息-感谢urllib3,keep alive是100%自动的 在一个会话内!您在会话中提出的任何请求都将 自动重用适当的连接

请注意,连接仅释放回池以供重用 一旦读取了所有身体数据;确保将
设置为
False
或读取
响应
对象的
内容
属性

那么,“如果可以”是什么意思?正如上面的文档所暗示的,如果您让流式响应对象保持活动状态,那么它们的连接显然无法重用

此外,连接池实际上是一个有限的缓存,而不是无限的,因此,如果你发送大量连接,其中两个连接到同一台服务器,你不会总是重复使用连接,只是经常重复使用。但通常情况下,这才是你真正想要的



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

全局函数,如
请求。获取
请求。发布
在每次调用时创建
请求。会话
实例。无法重用使用这些函数建立的连接,因为您无法访问自动创建的会话并将其连接池用于后续请求。如果您只需要执行几个请求,那么可以使用这些函数。否则,您将需要自己管理会话

这里是使用全局
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

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

非常感谢您的详细回复;这真的很有帮助。我还有一个问题。上述文件中的“会话”是什么?我通读了文档,实际上有一个会话对象。我通读了“requests”代码,并为每个请求创建了一个会话对象。因此,如果连接仅在会话中重复使用,那么我不确定如何在两个“get”调用之间重复使用连接。@gmemon:对不起,这是个错误的措辞。我的意思是组成全局状态的适配器集合,在本例中,具体地说是
HTTPAdapter
(这是保存
urllib3.PoolManager
)的东西)。我不知道什么是正确的术语,但“会话”显然是个错误的选择。我将编辑答案。感谢您指出这一点。这可能是
请求
模块可用的最佳答案,但它仍然不能令人满意,因为它将连接重用与会话处理混为一谈。仅仅因为我想在请求之间共享连接并不意味着我想共享cookies等。最好是像
请求这样的选项。enable_pooling()
以透明的方式启用由主机名和端口键入的池(被接受的答案错误地认为是默认值)。David Ongaro,你说得对。然而,这是对关于特定库的特定问题的回答。答案反映了库的实现。你的建议超出了这个问题的范围。我认为在请求库bug追踪器中讨论您的建议会更好。