Je collecte des statistiques sur une liste de sites Web et j'utilise des demandes pour cela par souci de simplicité. Voici mon code:
data=[]
websites=['http://google.com', 'http://bbc.co.uk']
for w in websites:
r= requests.get(w, verify=False)
data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) )
Maintenant, je veux requests.get
expirer après 10 secondes pour que la boucle ne reste pas bloquée.
Cette question a été d'intérêt avant aussi , mais aucune des réponses sont propres. Je mettrai un peu de prix là-dessus pour obtenir une bonne réponse.
J'ai entendu dire que ne pas utiliser les demandes est peut-être une bonne idée, mais comment puis-je obtenir les bonnes choses que les demandes offrent. (ceux du tuple)
python
timeout
python-requests
Kiarash
la source
la source
Réponses:
Qu'en est-il de l'utilisation de Eventlet? Si vous souhaitez expirer la demande après 10 secondes, même si des données sont reçues, cet extrait fonctionnera pour vous:
la source
eventlet.monkey_patch()
nécessaire?socket
module doit être monkey patché, donc au moins vous aurez besoin d'uneventlet.monkey_patch(socket=True)
requests.get('https://github.com', timeout=5)
Définissez le paramètre de délai :
Tant que vous ne définissez pas
stream=True
cette demande, cela entraînera l'requests.get()
expiration de l'appel à si la connexion prend plus de dix secondes ou si le serveur n'envoie pas de données pendant plus de dix secondes.la source
MISE À JOUR: https://requests.readthedocs.io/en/master/user/advanced/#timeouts
Dans la nouvelle version de
requests
:Si vous spécifiez une valeur unique pour le délai d'expiration, comme ceci:
La valeur du délai d'expiration sera appliquée à la fois au
connect
et auxread
délais d' expiration . Spécifiez un tuple si vous souhaitez définir les valeurs séparément:Si le serveur distant est très lent, vous pouvez dire aux requêtes d'attendre indéfiniment une réponse, en passant None comme valeur de délai d'expiration, puis en récupérant une tasse de café.
Ma vieille réponse (probablement obsolète) (qui a été publiée il y a longtemps):
Il existe d'autres moyens de surmonter ce problème:
1. Utilisez la
TimeoutSauce
classe interneDe: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896
2. Utilisez une fourchette de requêtes de kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout
De sa documentation: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst
kevinburke a demandé qu'il soit fusionné dans le projet de requêtes principal, mais il n'a pas encore été accepté.
la source
this won't work for you use-case
. Il voulait dire que cela ne fonctionnait pas avec le flux mp3 recherché par l'autre gars.timeout = int(seconds)
Depuis
requests >= 2.4.0
, vous pouvez utiliser l'timeout
argument, à savoir:Remarque:
la source
Pour créer un délai, vous pouvez utiliser des signaux .
La meilleure façon de résoudre ce cas est probablement de
try-except-finally
bloc.Voici un exemple de code:
Il y a quelques mises en garde à ceci:
Mais tout est dans la bibliothèque python standard! À l'exception de l'importation de la fonction de veille, il ne s'agit que d'une seule importation. Si vous comptez utiliser des délais d'attente à de nombreux endroits, vous pouvez facilement mettre TimeoutException, _timeout et le chant dans une fonction et l'appeler simplement. Ou vous pouvez créer un décorateur et le mettre sur des fonctions, voir la réponse ci-dessous.
Vous pouvez également le configurer en tant que "gestionnaire de contexte" afin de pouvoir l'utiliser avec l'
with
instruction:Un inconvénient possible avec cette approche de gestionnaire de contexte est que vous ne pouvez pas savoir si le code a réellement expiré ou non.
Sources et lectures recommandées:
la source
Essayez cette demande avec le délai d'expiration et la gestion des erreurs:
la source
Définir
stream=True
et utiliserr.iter_content(1024)
. Oui,eventlet.Timeout
ça ne marche pas pour moi.La discussion est ici https://redd.it/80kp1h
la source
Cela peut être excessif, mais la file d'attente des tâches distribuées Celery prend en charge les délais d'expiration.
En particulier, vous pouvez définir une limite de temps souple qui déclenche simplement une exception dans votre processus (afin que vous puissiez nettoyer) et / ou une limite de temps ferme qui met fin à la tâche lorsque la limite de temps a été dépassée.
Sous les couvertures, cela utilise la même approche de signaux que celle référencée dans votre article "avant", mais d'une manière plus utilisable et gérable. Et si la liste des sites Web que vous surveillez est longue, vous pouvez bénéficier de sa caractéristique principale - toutes sortes de façons de gérer l'exécution d'un grand nombre de tâches.
la source
python-requests
mais àhttplib
(utilisé par les requêtes pour Python 2.7). Le package transmet tout ce qui concernetimeout
directement à httplib. Je pense que rien ne peut être corrigé dans la demande car le processus peut rester longtemps dans httplib.Je pense que vous pouvez utiliser
multiprocessing
et ne pas dépendre d'un package tiers:Le délai passé à
kwargs
est le délai pour obtenir une réponse du serveur, l'argumenttimeout
est le délai pour obtenir la réponse complète .la source
timeout = (timeout de connexion, timeout de lecture des données) ou donner un seul argument (timeout = 1)
la source
ce code fonctionne pour socketError 11004 et 10060 ......
la source
Bien que la question porte sur les demandes, je trouve cela très facile à faire avec pycurl CURLOPT_TIMEOUT ou CURLOPT_TIMEOUT_MS.
Aucun filetage ni signalisation requis:
la source
Si vous utilisez l'option,
stream=True
vous pouvez le faire:La solution n'a pas besoin de signaux ou de multi-traitement.
la source
Juste une autre solution (obtenue à partir de http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads )
Avant de télécharger, vous pouvez connaître la taille du contenu:
Mais attention, un expéditeur peut définir une valeur incorrecte dans le champ de réponse 'content-length'.
la source
Si cela arrive, créez un thread de surveillance qui gâche l'état interne des requêtes après 10 secondes, par exemple:
Notez qu'en fonction des bibliothèques système, vous ne pourrez peut-être pas définir la date limite de résolution DNS.
la source
Eh bien, j'ai essayé de nombreuses solutions sur cette page et j'ai toujours rencontré des instabilités, des blocages aléatoires, de mauvaises performances de connexion.
J'utilise maintenant Curl et je suis vraiment content de sa fonctionnalité "max time" et des performances globales, même avec une implémentation aussi médiocre:
Ici, j'ai défini un paramètre de temps maximum de 6 secondes, englobant à la fois le temps de connexion et le temps de transfert.
Je suis sûr que Curl a une belle liaison python, si vous préférez vous en tenir à la syntaxe pythonique :)
la source
Il existe un package appelé timeout-decorator que vous pouvez utiliser pour expirer n'importe quelle fonction python.
Il utilise l'approche des signaux que suggèrent certaines réponses ici. Vous pouvez également lui dire d'utiliser le multitraitement au lieu des signaux (par exemple, si vous êtes dans un environnement multi-thread).
la source
J'utilise les requêtes 2.2.1 et eventlet n'a pas fonctionné pour moi. Au lieu de cela, j'ai pu utiliser gevent timeout à la place puisque gevent est utilisé dans mon service pour gunicorn.
Veuillez noter que gevent.timeout.Timeout n'est pas intercepté par la gestion générale des exceptions. Donc, soit explicitement attraper,
gevent.timeout.Timeout
soit transmettre une exception différente à utiliser comme ceci:with gevent.Timeout(5, requests.exceptions.Timeout):
bien qu'aucun message ne soit passé lorsque cette exception est déclenchée.la source
J'ai trouvé une solution plus directe, certes moche, mais qui résout le vrai problème. Ça va un peu comme ça:
Vous pouvez lire l'explication complète ici
la source
timeout
paramètrerequests.get()
sans solutions de contournement laides 2- bien que les deux ne limitent pas le délai total contrairement àeventlet.Timeout(10)