web-dev-qa-db-fra.com

Requêtes asynchrones avec Python requêtes

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

Remarque

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:

  1. Définir une fonction pour ce que vous voulez faire avec chaque objet (votre tâche)
  2. Ajouter cette fonction en tant que hook d'événement dans votre demande
  3. Appelez async.map sur une liste de toutes les demandes/actions

Exemple:

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)
138
Jeff

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?

installation:

$ pip install grequests

usage:

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.

71
outforawhile

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
40
Anton Shelin

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.

26
Dreampuf

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/

7
Monkey Boson
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...
5
Jason Pump

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.

2
David Watson

Si vous souhaitez utiliser asyncio, alors requests-async fournit une fonctionnalité async/wait pour requests - https://github.com/encode/requests-async

2
Tom Christie

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

0
Sam