我正在使用python的HTTP通信请求模块,我想知道如何重用已经建立的TCP连接?请求模块是无状态的,如果我反复调用get获取相同的URL,那么每次都会创建一个新连接吗?
谢谢!
答案 0 :(得分:38)
requests.get
或requests.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连接。有关更多信息,请阅读文档。