J'ai essayé l'exemple fourni dans la documentation de bibliothèque de requêtes pour python.
Avec async.map(rs)
, je reçois les codes de réponse, mais je souhaite obtenir le contenu de chaque page demandée. Ceci, par exemple, ne fonctionne pas:
out = async.map(rs)
print out[0].content
La réponse ci-dessous est non applicable aux requêtes v0.13.0 +. La fonctionnalité asynchrone a été déplacée vers grequests après l’écriture de cette question. Cependant, vous pouvez simplement remplacer requests
par grequests
ci-dessous et cela devrait fonctionner.
J'ai laissé cette réponse en l'état pour refléter la question initiale qui concernait l'utilisation des requêtes <v0.13.0.
Pour effectuer plusieurs tâches avec async.map
de manière asynchrone , vous devez:
async.map
sur une liste de toutes les demandes/actionsExemple:
from requests import async
# If using requests > v0.13.0, use
# from grequests import async
urls = [
'http://python-requests.org',
'http://httpbin.org',
'http://python-guide.org',
'http://kennethreitz.com'
]
# A simple task to do to each response object
def do_something(response):
print response.url
# A list to hold our things to do via async
async_list = []
for u in urls:
# The "hooks = {..." part is where you define what you want to do
#
# Note the lack of parentheses following do_something, this is
# because the response will be used as the first argument automatically
action_item = async.get(u, hooks = {'response' : do_something})
# Add the task to our list of things to do via async
async_list.append(action_item)
# Do our list of things to do via async
async.map(async_list)
async
est maintenant un module indépendant: grequests
.
Voir ici: https://github.com/kennethreitz/grequests
Et là: Méthode idéale pour envoyer plusieurs requêtes HTTP via Python?
$ pip install grequests
construire une pile:
import grequests
urls = [
'http://www.heroku.com',
'http://tablib.org',
'http://httpbin.org',
'http://python-requests.org',
'http://kennethreitz.com'
]
rs = (grequests.get(u) for u in urls)
envoyer la pile
grequests.map(rs)
le résultat ressemble à
[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>]
les requêtes ne semblent pas définir de limite pour les demandes simultanées, c'est-à-dire lorsque plusieurs demandes sont envoyées au même serveur.
J'ai testé les deux demandes-futures et grequests. Grequests est plus rapide mais apporte des correctifs pour les singes et des problèmes supplémentaires avec les dépendances. request-futures est plusieurs fois plus lent que les grequests. J'ai décidé d'écrire mes propres requêtes et simplement emballées dans ThreadPollExecutor et c'était presque aussi rapide que les grequests, mais sans dépendances externes.
import requests
import concurrent.futures
def get_urls():
return ["url1","url2"]
def load_url(url, timeout):
return requests.get(url, timeout = timeout)
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
future_to_url = {executor.submit(load_url, url, 10): url for url in get_urls()}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
resp_err = resp_err + 1
else:
resp_ok = resp_ok + 1
peut-être demandes-futures est un autre choix.
from requests_futures.sessions import FuturesSession
session = FuturesSession()
# first request is started in background
future_one = session.get('http://httpbin.org/get')
# second requests is started immediately
future_two = session.get('http://httpbin.org/get?foo=bar')
# wait for the first request to complete, if it hasn't already
response_one = future_one.result()
print('response one status: {0}'.format(response_one.status_code))
print(response_one.content)
# wait for the second request to complete, if it hasn't already
response_two = future_two.result()
print('response two status: {0}'.format(response_two.status_code))
print(response_two.content)
Il est également recommandé dans le document office . Si vous ne voulez pas impliquer gevent, c'est un bon choix.
Je sais que cela a été fermé pendant un certain temps, mais j’ai pensé qu’il pourrait être utile de promouvoir une autre solution async basée sur la bibliothèque de requêtes.
list_of_requests = ['http://moop.com', 'http://doop.com', ...]
from simple_requests import Requests
for response in Requests().swarm(list_of_requests):
print response.content
Les documents sont ici: http://pythonhosted.org/simple-requests/
threads=list()
for requestURI in requests:
t = Thread(target=self.openURL, args=(requestURI,))
t.start()
threads.append(t)
for thread in threads:
thread.join()
...
def openURL(self, requestURI):
o = urllib2.urlopen(requestURI, timeout = 600)
o...
J'utilise depuis un certain temps python demandes d'appels asynchrones contre l'API Gist de Github.
Pour un exemple, voyez le code ici:
https://github.com/davidthewatson/flasgist/blob/master/views.py#L60-72
Ce style de python n'est peut-être pas l'exemple le plus clair, mais je peux vous assurer que le code fonctionne. Faites-moi savoir si cela vous déroute et je le documenterai.
Si vous souhaitez utiliser asyncio, alors requests-async
fournit une fonctionnalité async/wait pour requests
- https://github.com/encode/requests-async
J'ai aussi essayé certaines choses en utilisant les méthodes asynchrones en python. Cependant, j'ai eu beaucoup plus de chance en utilisant twisted pour la programmation asynchrone. Il a moins de problèmes et est bien documenté. Voici un lien de quelque chose de similaire à ce que vous essayez de tordu.
http://pythonquirks.blogspot.com/2011/04/twisted-asynchronous-http-request.html