2014-07-21 15 views
5

Ich arbeite mit Pythons Requests-Modul für die HTTP-Kommunikation, und ich frage mich, wie bereits bestehende TCP-Verbindungen wiederverwenden? Das Request-Modul ist zustandslos und wenn ich wiederholt für dieselbe URL getaufe, würde es nicht jedes Mal eine neue Verbindung erstellen?Python Anfragen Modul und Verbindung wiederverwenden

Danke !!

+0

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

Antwort

5

Das Requests-Modul ist zustandslos und wenn ich wiederholt für die gleiche URL abrufen, würde es nicht jedes Mal eine neue Verbindung erstellen?

Das Modul requests ist nicht zustandslos; Sie können den Status einfach ignorieren und effektiv einen globalen Singleton-Status verwenden, wenn Sie dies wünschen. *

Und es (oder vielmehr eine der zugrunde liegenden Bibliotheken, urllib3) verwaltet einen Verbindungspool, der durch (hostname, Port) Paar, so wird es in der Regel nur magisch eine Verbindung wiederverwenden, wenn es möglich ist.

Wie the documentation sagt:

Ausgezeichnete Nachrichten - dank urllib3, keep-alive ist 100% automatische innerhalb einer Sitzung! Alle Anfragen, die Sie innerhalb einer Sitzung stellen, automatisch die entsprechende Verbindung wiederverwenden!

Beachten Sie, dass die Verbindungen erst wieder zur Wiederverwendung in den Pool freigegeben werden, nachdem alle Daten des Körpers gelesen wurden ; Stellen Sie sicher, dass Sie entweder stream auf False setzen oder die content Eigenschaft des Objekts Response lesen.

Also, was bedeutet "wenn es kann"? Wie die obigen Dokumente zeigen, können Ihre Verbindungen, wenn Sie Streaming-Response-Objekte am Leben erhalten, offensichtlich nicht wiederverwendet werden.

Auch ist der Verbindungspool wirklich eine endliche Cache, nicht unendlich ist, also, wenn Sie eine Tonne Verbindungen Spam und zwei von ihnen auf dem gleichen Server sind, werden Sie nicht immer die Verbindung wieder verwenden, nur oft. Aber das ist normalerweise das, was du eigentlich willst.


* Der jeweilige Zustand relevant ist hier die transport adapter. Jede Sitzung erhält einen Transportadapter. Sie können den Adapter manuell angeben, oder Sie können einen globalen Standard angeben, oder Sie können einfach den standardmäßigen globalen Standard verwenden, der im Grunde nur einen urllib3.PoolManager zum Verwalten seiner HTTP-Verbindungen umschließt. Weitere Informationen finden Sie in der Dokumentation.

+1

Vielen Dank für die ausführliche Antwort; Das ist sehr hilfreich. Ich habe noch eine Frage. Was ist "Sitzung" in der oben genannten Dokumentation? Ich lese das Dokument durch und es gibt tatsächlich ein Session-Objekt. Ich lese den "Anfragen" -Code durch und für jede Anfrage wird ein Session-Objekt erstellt. Wenn Verbindungen nur innerhalb einer Sitzung wiederverwendet werden, bin ich mir nicht sicher, wie eine Verbindung zwischen zwei "Get" -Aufrufen wiederverwendet wird. – gmemon

+0

@gmemon: Entschuldigung, das war eine schlechte Formulierung. Was ich meinte, ist die Sammlung von Adaptern, die den globalen Zustand ausmachen, in diesem Fall speziell der "HTTPAdapter" (was der 'urllib3.PoolManager' ist). Ich weiß nicht, was der richtige Ausdruck dafür ist, aber "Sitzung" ist offensichtlich eine schlechte Wahl. Ich werde die Antwort bearbeiten. Danke, dass du darauf hingewiesen hast. – abarnert

18

Globale Funktionen wie requests.get oder requests.post erstellen die requests.Session Instanz auf jeden Anruf. Verbindungen, die mit diesen Funktionen hergestellt wurden, können nicht wiederverwendet werden, da Sie nicht auf automatisch erstellte Sitzungen zugreifen und den Verbindungspool für nachfolgende Anforderungen verwenden können. Es ist in Ordnung, diese Funktionen zu verwenden, wenn Sie nur ein paar Anfragen haben. Andernfalls sollten Sie die Sitzungen selbst verwalten.

Hier ist eine schnelle Anzeige der requests Verhalten, wenn Sie globale get Funktion und Sitzung verwenden.

Vorbereitung, nicht wirklich relevant für die Frage:

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

See, neue Verbindung jedes Mal, wenn get rufen etabliert:

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

Aber wenn Sie verwenden die gleiche Sitzung für nachfolgende Anrufe, neue Verbindung wird nicht für jede Anforderung erstellt:

>>> 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") 

Leistung:

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

Funktioniert viel schneller, wenn Sie die Sitzung (und damit den Verbindungspool der Sitzung) wiederverwenden.

Verwandte Themen