2010-11-07 2 views
11

Ich habe Code wie folgt.Mehrere (asynchrone) Verbindungen mit urllib2 oder einer anderen http-Bibliothek?

for p in range(1,1000): 
    result = False 
    while result is False: 
     ret = urllib2.Request('http://server/?'+str(p)) 
     try: 
      result = process(urllib2.urlopen(ret).read()) 
     except (urllib2.HTTPError, urllib2.URLError): 
      pass 
    results.append(result) 

Ich möchte zwei oder drei Anfragen gleichzeitig machen, um dies zu beschleunigen. Kann ich urllib2 dafür verwenden und wie? Wenn nicht welche andere Bibliothek sollte ich verwenden? Vielen Dank.

Antwort

0

Entweder Sie herausfinden, threads, oder Sie use Twisted (which is asynchronous).

+3

Koroutine-basierten Bibliotheken haben die Vorteile beider und einfacher als Fäden und Verdreht: GEVENT, eventlet, concurrence –

9

Werfen Sie einen Blick auf gevent - eine Coroutine-basierte Python-Netzwerkbibliothek, die Greenlet verwendet, um eine High-Level-synchrone API zusätzlich zur Libevent-Ereignisschleife bereitzustellen.

Beispiel:

#!/usr/bin/python 
# Copyright (c) 2009 Denis Bilenko. See LICENSE for details. 

"""Spawn multiple workers and wait for them to complete""" 

urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org'] 

import gevent 
from gevent import monkey 

# patches stdlib (including socket and ssl modules) to cooperate with other greenlets 
monkey.patch_all() 

import urllib2 


def print_head(url): 
    print 'Starting %s' % url 
    data = urllib2.urlopen(url).read() 
    print '%s: %s bytes: %r' % (url, len(data), data[:50]) 

jobs = [gevent.spawn(print_head, url) for url in urls] 

gevent.joinall(jobs) 
0

vielleicht multiprocessing mit und teilen Sie auf 2 Prozess arbeiten oder so.

Hier ist ein Beispiel (nicht getestet ist)

import multiprocessing 
import Queue 
import urllib2 


NUM_PROCESS = 2 
NUM_URL = 1000 


class DownloadProcess(multiprocessing.Process): 
    """Download Process """ 

    def __init__(self, urls_queue, result_queue): 

     multiprocessing.Process.__init__(self) 

     self.urls = urls_queue 
     self.result = result_queue 

    def run(self): 
     while True: 

      try: 
       url = self.urls.get_nowait() 
      except Queue.Empty: 
       break 

      ret = urllib2.Request(url) 
      res = urllib2.urlopen(ret) 

      try: 
       result = res.read() 
      except (urllib2.HTTPError, urllib2.URLError): 
        pass 

      self.result.put(result) 


def main(): 

    main_url = 'http://server/?%s' 

    urls_queue = multiprocessing.Queue() 
    for p in range(1, NUM_URL): 
     urls_queue.put(main_url % p) 

    result_queue = multiprocessing.Queue() 

    for i in range(NUM_PROCESS): 
     download = DownloadProcess(urls_queue, result_queue) 
     download.start() 

    results = [] 
    while result_queue: 
     result = result_queue.get() 
     results.append(result) 

    return results 

if __name__ == "__main__": 
    results = main() 

    for res in results: 
     print(res) 
+0

Threading ist die richtige Antwort, nicht komplex geschichteten Dinge wie Verdrehte. Ich würde Threading anstatt Multiprocessing verwenden; Das prozessbasierte Multiprocessing-Modul wird nur für CPU-gebundene Tasks benötigt, nicht für diese I/O-gebundenen Tasks. –

10

Sie asynchrone IO dies zu tun, verwenden können.

requests + gevent = grequests

GRequests können Sie Anfragen mit GEVENT verwenden, um asynchrone HTTP-Requests leicht zu machen.

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) 
grequests.map(rs) 
+0

Können Sie detailliert beschreiben, wie Sie eine Funktion zur Verarbeitung der Antwort übergeben? Docs scheinen es nicht zu erwähnen – Overdrivr

+0

@Overdrive Sie können http://docs.python-requests.org/en/master/user/advanced/#event-hooks Beispiel: 'grequests.get (u, hooks = dict (response = print_url)) 'oder Sie können' grequests.get (u, callback = print_url) 'verwenden – Chaker

1

Ich weiß, diese Frage ein wenig alt, aber ich dachte, es nützlich sein könnte, eine weitere Asynchron-Lösung auf die Anfragen Bibliothek gebaut zu fördern.

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 

Die docs sind hier: http://pythonhosted.org/simple-requests/

4

Also, es ist 2016 und wir haben Python 3.4+ mit eingebautem in asyncio Modul für asynchrones I/O. Wir können aiohttp als HTTP-Client verwenden, um mehrere URLs parallel herunterzuladen.

import asyncio 
from aiohttp import ClientSession 

async def fetch(url): 
    async with ClientSession() as session: 
     async with session.get(url) as response: 
      return await response.read() 

async def run(loop, r): 
    url = "http://localhost:8080/{}" 
    tasks = [] 
    for i in range(r): 
     task = asyncio.ensure_future(fetch(url.format(i))) 
     tasks.append(task) 

    responses = await asyncio.gather(*tasks) 
    # you now have all response bodies in this variable 
    print(responses) 

loop = asyncio.get_event_loop() 
future = asyncio.ensure_future(run(loop, 4)) 
loop.run_until_complete(future) 

Quelle: Kopie kleistert von http://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

Verwandte Themen