web-dev-qa-db-fra.com

python demande la réutilisation du module et de la connexion

Je travaille avec le module de requêtes de python pour la communication HTTP et je me demande comment réutiliser les connexions TCP déjà établies)? Le module de requêtes est sans état et si j'appelle à plusieurs reprises get pour la même URL, ne ça crée pas une nouvelle connexion à chaque fois?

Merci!!

20
gmemon

Le module des demandes est sans état et si j'appelle à plusieurs reprises get pour la même URL, ne créerait-il pas une nouvelle connexion à chaque fois?

Le module requests n'est pas sans état; il vous permet simplement d'ignorer l'état et d'utiliser efficacement un état singleton global si vous le souhaitez. *

Et il (ou, plutôt, l'une des bibliothèques sous-jacentes, urllib3) maintient un pool de connexions codé par une paire (nom d'hôte, port), donc il réutilise généralement comme par magie une connexion s'il le peut.

Comme la documentation dit:

Excellente nouvelle - grâce à urllib3, keep-alive est 100% automatique en une session! Toutes les demandes que vous faites dans une session réutilisent automatiquement la connexion appropriée!

Notez que les connexions ne sont renvoyées au pool pour réutilisation qu'une fois que toutes les données du corps ont été lues; assurez-vous de définir stream sur False ou de lire la propriété content de l'objet Response.

Alors, que signifie "si cela peut"? Comme le suggèrent les documents ci-dessus, si vous gardez en vie les objets de réponse en streaming, leurs connexions ne peuvent évidemment pas être réutilisées.

De plus, le pool de connexions est vraiment un cache fini, pas infini, donc si vous envoyez du spam sur une tonne de connexions et que deux d'entre elles sont sur le même serveur, vous ne serez pas toujours réutiliser la connexion, juste souvent . Mais généralement, c'est ce que vous voulez réellement.


* L'état particulier pertinent ici est le adaptateur de transport . Chaque session reçoit un adaptateur de transport. Vous pouvez spécifier l'adaptateur manuellement, ou vous pouvez spécifier une valeur par défaut globale, ou vous pouvez simplement utiliser la valeur par défaut globale par défaut, qui se résume simplement à un urllib3.PoolManager pour gérer ses connexions HTTP. Pour plus d'informations, lisez la documentation.

5
abarnert

Fonctions globales comme requests.get ou requests.post créer le requests.Session instance à chaque appel. Les connexions établies avec ces fonctions ne peuvent pas être réutilisées, car vous ne pouvez pas accéder à la session créée automatiquement et utiliser son pool de connexions pour les requêtes suivantes. C'est bien d'utiliser ces fonctions si vous n'avez qu'à faire quelques demandes. Sinon, vous voudrez gérer les sessions vous-même.

Voici un affichage rapide du comportement de requests lorsque vous utilisez la fonction et la session globale get.

Préparation, pas vraiment pertinente à la question:

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

Vous voyez, une nouvelle connexion est établie chaque fois que vous appelez 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

Mais si vous utilisez la même session pour les appels suivants, la connexion est réutilisée:

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

Performance:

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

Fonctionne beaucoup plus rapidement lorsque vous réutilisez la session (et donc le pool de connexions de la session).

49
Dmytro Kyrychuk