J'ouvre un fichier contenant 100 000 URL. Je dois envoyer une demande HTTP à chaque URL et imprimer le code d'état. J'utilise Python 2.6, et jusqu'à présent, j'ai examiné les nombreuses façons confuses que Python implémente le threading / simultanéité. J'ai même regardé la bibliothèque de concours python , mais je ne sais pas comment écrire correctement ce programme. Quelqu'un a-t-il rencontré un problème similaire? Je suppose qu'en général, j'ai besoin de savoir comment effectuer des milliers de tâches en Python aussi rapidement que possible - je suppose que cela signifie «simultanément».
python
http
concurrency
IgorGanapolsky
la source
la source
requests.get
etrequests.head
(c'est-à-dire une demande de page vs une demande de tête) de renvoyer différents codes d'état, donc ce n'est pas le meilleur conseilRéponses:
Solution sans torsion:
Celui-ci est légèrement plus rapide que la solution torsadée et utilise moins de CPU.
la source
concurrent*2
?conn.close()
. L'ouverture d'un trop grand nombre de connexions http peut interrompre votre script à un moment donné et manger de la mémoire.Queue
module a été renomméqueue
en Python 3. Il s'agit du code Python 2.Une solution utilisant la bibliothèque de mise en réseau asynchrone tornado
la source
Les choses ont beaucoup changé depuis 2010, lorsque cela a été publié et je n'ai pas essayé toutes les autres réponses, mais j'en ai essayé quelques-unes, et j'ai trouvé que cela fonctionnait le mieux pour moi en utilisant python3.6.
J'ai pu récupérer environ 150 domaines uniques par seconde sur AWS.
la source
time1 = time.time()
en haut de la boucle for ettime2 = time.time()
juste après la boucle for.Les discussions ne sont absolument pas la réponse ici. Ils fourniront à la fois des goulots d'étranglement de processus et de noyau, ainsi que des limites de débit qui ne sont pas acceptables si l'objectif global est "le moyen le plus rapide".
Un peu de
twisted
et sonHTTP
client asynchrone vous donneraient de bien meilleurs résultats.la source
Je sais que c'est une vieille question, mais en Python 3.7 vous pouvez le faire en utilisant
asyncio
etaiohttp
.Vous pouvez en savoir plus à ce sujet et voir un exemple ici .
la source
urls= [fetch(construct_fetch_url(u),idx) for idx, u in enumerate(some_URI_list)]
results = await asyncio.gather(*urls)
Utilisez les grequests , c'est une combinaison de requêtes + module Gevent.
GRequests vous permet d'utiliser des requêtes avec Gevent pour créer facilement des requêtes HTTP asynchrones.
L'utilisation est simple:
Créez un ensemble de demandes non envoyées:
Envoyez-les tous en même temps:
la source
Une bonne approche pour résoudre ce problème consiste à écrire d'abord le code requis pour obtenir un résultat, puis à incorporer du code de thread pour paralléliser l'application.
Dans un monde parfait, cela signifierait simplement démarrer simultanément 100 000 threads qui produisent leurs résultats dans un dictionnaire ou une liste pour un traitement ultérieur, mais en pratique, vous êtes limité dans le nombre de requêtes HTTP parallèles que vous pouvez émettre de cette manière. Localement, vous avez des limites dans le nombre de sockets que vous pouvez ouvrir simultanément, le nombre de threads d'exécution autorisés par votre interpréteur Python. À distance, le nombre de connexions simultanées peut être limité si toutes les demandes concernent un ou plusieurs serveurs. Ces limitations nécessiteront probablement que vous écriviez le script de manière à interroger uniquement une petite fraction des URL à la fois (100, comme une autre affiche l'a mentionné, est probablement une taille de pool de threads décente, bien que vous puissiez constater que vous peut déployer avec succès beaucoup plus).
Vous pouvez suivre ce modèle de conception pour résoudre le problème ci-dessus:
list
oudict
dans CPython, vous pouvez ajouter ou insérer en toute sécurité des éléments uniques de vos threads sans verrous , mais si vous écrivez dans un fichier ou si vous avez besoin d'une interaction de données cross-thread plus complexe, vous devez utiliser un verrouillage d'exclusion mutuelle pour protéger cet état de la corruption .Je vous suggère d'utiliser le module de threading . Vous pouvez l'utiliser pour lancer et suivre les threads en cours d'exécution. Le support de threading de Python est nu, mais la description de votre problème suggère qu'il est complètement suffisant pour vos besoins.
Enfin, si vous souhaitez voir une application assez simple d'une application de réseau parallèle écrit en Python, consultez ssh.py . Il s'agit d'une petite bibliothèque qui utilise le threading Python pour paralléliser de nombreuses connexions SSH. La conception est suffisamment proche de vos besoins pour que vous puissiez la trouver comme une bonne ressource.
la source
Si vous cherchez à obtenir les meilleures performances possibles, vous pouvez envisager d'utiliser des E / S asynchrones plutôt que des threads. La surcharge associée à des milliers de threads du système d'exploitation n'est pas anodine et le changement de contexte dans l'interpréteur Python en ajoute encore plus. Le filetage fera certainement l'affaire, mais je soupçonne qu'un itinéraire asynchrone fournira de meilleures performances globales.
Plus précisément, je suggère le client Web asynchrone dans la bibliothèque Twisted ( http://www.twistedmatrix.com ). Il a certes une courbe d'apprentissage abrupte mais il est assez facile à utiliser une fois que vous maîtrisez le style de programmation asynchrone de Twisted.
Un HowTo sur l'API client Web asynchrone de Twisted est disponible à l'adresse suivante:
http://twistedmatrix.com/documents/current/web/howto/client.html
la source
Une solution:
Temps de test:
Pingtime:
la source
L'utilisation d'un pool de threads est une bonne option et rendra cela assez facile. Malheureusement, python n'a pas de bibliothèque standard qui rend les pools de threads ultra faciles. Mais voici une bibliothèque décente qui devrait vous aider à démarrer: http://www.chrisarndt.de/projects/threadpool/
Exemple de code de leur site:
J'espère que cela t'aides.
la source
q_size
> 0, la taille de la file d'attente des demandes de travail est limitée et le pool de threads se bloque lorsque la file d'attente est pleine et il essaie d'y placer plus de demandes de travail (voirputRequest
méthode), sauf si vous utilisez également unetimeout
valeur positive pourputRequest
."Créez un
epoll
objet,ouvrez de nombreuses sockets TCP client,
ajustez leurs tampons d'envoi pour être un peu plus que l'en-tête de demande,
envoyez un en-tête de demande - cela devrait être immédiat, il suffit de le placer dans un tampon, d'enregistrer le socket dans l'
epoll
objet, de lefaire
.poll
surepoll
obect, delire en premier 3 octets de chaque socket
.poll
,écrivez-les
sys.stdout
puis\n
(ne pas vider), fermez le socket client.Limitez le nombre de sockets ouvertes simultanément - gérez les erreurs lors de la création de sockets. Créez un nouveau socket uniquement si un autre est fermé.
Ajustez les limites du système d'exploitation.
Essayez de vous lancer dans quelques (peu) processus: cela peut aider à utiliser le processeur un peu plus efficacement.
la source
Pour votre cas, le filetage fera probablement l'affaire, car vous passerez probablement le plus de temps à attendre une réponse. Il existe des modules utiles comme Queue dans la bibliothèque standard qui pourraient vous aider.
J'ai fait une chose similaire avec le téléchargement parallèle de fichiers auparavant et c'était assez bon pour moi, mais ce n'était pas à l'échelle dont vous parlez.
Si votre tâche était plus liée au CPU, vous voudrez peut-être regarder le module multiprocessing , qui vous permettra d'utiliser plus de CPU / cores / threads (plus de processus qui ne se bloqueront pas puisque le verrouillage est par processus)
la source
Pensez à utiliser Windmill , bien que Windmill ne puisse probablement pas faire autant de threads.
Vous pouvez le faire avec un script Python roulé à la main sur 5 machines, chacune se connectant sortante à l'aide des ports 40000-60000, ouvrant 100 000 connexions de port.
En outre, il peut être utile de faire un exemple de test avec une application d'assurance qualité bien filetée telle que OpenSTA afin de se faire une idée de la capacité de chaque serveur.
Aussi, essayez de regarder simplement en utilisant Perl simple avec la classe LWP :: ConnCache. Vous obtiendrez probablement plus de performances (plus de connexions) de cette façon.
la source
Ce client Web asynchrone tordu va assez vite.
la source
J'ai trouvé que l'utilisation du
tornado
package était le moyen le plus rapide et le plus simple d'y parvenir:la source
La manière la plus simple serait d'utiliser la bibliothèque de threads intégrée de Python.
Ce ne sont pas de «vrais» threads / noyauIls ont des problèmes (comme la sérialisation), mais sont assez bons. Vous souhaitez un pool de files d'attente et de threads. Une option est ici , mais il est trivial d'écrire la vôtre. Vous ne pouvez pas paralléliser tous les 100 000 appels, mais vous pouvez en lancer 100 (ou plus) en même temps.la source