我正在使用Python的requests模块进行HTTP通信,想知道如何重用已经建立的TCP连接?由于requests模块是无状态的,如果我多次调用相同URL的get方法,那么它每次都会创建一个新的连接吗?
谢谢!
我正在使用Python的requests模块进行HTTP通信,想知道如何重用已经建立的TCP连接?由于requests模块是无状态的,如果我多次调用相同URL的get方法,那么它每次都会创建一个新的连接吗?
谢谢!
全局函数,例如requests.get
或requests.post
,在每次调用时都创建requests.Session
实例。使用这些函数发起的连接不能被重用,因为无法访问自动创建的会话并使用其连接池进行后续请求。如果您只需要执行少量请求,使用这些函数是可以的。否则,您需要手动管理会话。
下面是一个快速演示当您使用全局get
函数和会话时requests
的行为。
准备工作,与问题无关:
>>> 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.enable_pooling()
,以透明地启用按主机名和端口分组的连接池(正如被接受的答案错误地建议的那样是默认值)。 - David Ongarorequests模块不是无状态的;它允许你忽略状态并在需要时实现全局单例状态。
而且它(或者更准确地说,其中一个底层库urllib3)维护了一个由(主机名,端口)对键控的连接池,如果可以的话,它通常会自动重用连接。
正如文档中所述:
非常好的消息--多亏了urllib3,在会话内保持活动100%自动完成!在会话中发出的任何请求都会自动重复使用适当的连接!
请注意,只有在读取所有正文数据后,连接才会释放回到池中以供重用;一定要将流设置为False或读取Response对象的content属性。
那么,“如果可以”的意思是什么呢?就像上面的文档暗示的那样,如果您保持流响应对象处于活动状态,它们的连接显然无法重复使用。
此外,连接池实际上是有限的缓存,而不是无限的,因此如果您大量创建连接并且其中两个连接到同一个服务器,则不会始终重用连接,只是经常重用。但通常,这正是您想要的。
* 这里涉及到的特定状态是传输适配器。每个会话都有一个传输适配器。您可以手动指定适配器,也可以指定全局默认值,或者只使用默认全局默认值,它基本上只是包装了一个urllib3.PoolManager
来管理其HTTP连接。有关更多信息,请阅读文档。
HTTPAdapter
(它持有urllib3.PoolManager
的东西)。我不知道正确的术语是什么,但“会话”显然是一个糟糕的选择。我会编辑答案。感谢您指出这一点。 - abarnert