2014-07-21 96 views
5

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

谢谢!

+0

http://docs.python-requests.org/en/latest/user/advanced/#keep-alive – dm03514

回答

5

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

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

而它(或者,而是其中一个底层库,urllib3)维护一个连接池(主机名,端口)对,所以如果可能的话,它通常会神奇地重用连接。

由于the documentation说:

极好的消息 - 由于urllib3,保活是在一个会话中100%自动 !您在任何会话中发出的任何请求都会自动重复使用相应的连接!

请注意,一旦所有的主体数据都被读取,连接只会被释放回池以供重用 ;请确保将stream设置为 False或者读取Response对象的content属性。

那么,“如果可以”意味着什么?正如上面的文档所暗示的,如果你保持流式响应对象的活着,它们的连接显然不能被重用。

此外,连接池确实是一个有限的缓存,而不是无限的,所以如果您的垃圾邮件了一吨的连接,其中两个是在同一台服务器,你不会总是重用的连接,只需通常是。但通常情况下,这就是你真正想要的。


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

+1

非常感谢您的详细回复;这真的很有帮助。我还有一个问题。上述文档中的“会话”是什么?我通读了文档,实际上有一个Session对象。我通读了“请求”代码,并为每个请求创建了一个Session对象。所以,如果连接只在Session中重用,那么我不确定在两个“get”调用之间连接将被重用。 – gmemon

+0

@gmemon:对不起,这是不好的措辞。我的意思是构成全局状态的适配器的集合,在这种情况下,特别是'HTTPAdapter'(这是持有'urllib3.PoolManager'的东西)。我不知道这是对的,但“会议”显然是一个不错的选择。我会编辑答案。感谢您指出了这一点。 – abarnert

18

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

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

准备,没有真正的问题有关:

>>> _ = 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 

但是如果你使用同一个会话的后续调用,新:

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

见,新的连接在每次调用get时间确定不会为每个请求创建连接:

>>> 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 
当你重用会话(从而会话的连接池)

工程快得多。