2010-11-07 26 views
11

Tôi có mã như thế này.Nhiều kết nối (không đồng bộ) với urllib2 hoặc thư viện http khác?

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) 

Tôi muốn thực hiện hai hoặc ba yêu cầu cùng một lúc để đẩy nhanh quá trình này. Tôi có thể sử dụng urllib2 cho việc này không và làm thế nào? Nếu tôi không sử dụng thư viện nào khác? Cảm ơn.

Trả lời

0

Hoặc bạn tìm ra threads hoặc bạn use Twisted (which is asynchronous).

+3

thư viện coroutine-based có những lợi ích của cả hai và đơn giản hơn đề và Twisted: gevent, eventlet, sự đồng –

9

Hãy xem gevent - thư viện mạng Python dựa trên coroutine sử dụng greenlet để cung cấp API đồng bộ cao cấp ở đầu vòng lặp sự kiện không thích hợp.

Ví dụ:

#!/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

có thể sử dụng multiprocessing và chia bạn làm việc trên 2 quá trình hoặc lâu hơn.

Dưới đây là một ví dụ (nó không được kiểm tra)

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 là câu trả lời đúng, không phải thứ lớp phức tạp như Xoắn. Tôi muốn sử dụng luồng hơn là đa xử lý; mô-đun đa xử lý dựa trên quy trình chỉ cần thiết cho các tác vụ ràng buộc CPU, không phải là mô-đun I/O ràng buộc này. –

10

Bạn có thể sử dụng đồng bộ IO để làm điều này.

requests + gevent = grequests

GRequests phép bạn sử dụng yêu cầu với Gevent để làm cho yêu cầu HTTP không đồng bộ một cách dễ dàng.

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

Bạn có thể nêu chi tiết cách vượt qua một hàm để xử lý phản hồi không? Tài liệu dường như không đề cập đến nó – Overdrivr

+0

@Overdrivr Bạn có thể sử dụng http://docs.python-requests.org/en/master/user/advanced/#event-hooks ví dụ: 'grequests.get (u, hooks = dict (response = print_url)) 'hoặc bạn có thể sử dụng' grequests.get (u, callback = print_url) ' – Chaker

1

Tôi biết câu hỏi này hơi cũ nhưng tôi nghĩ có thể hữu ích khi quảng cáo giải pháp không đồng bộ khác được xây dựng trên thư viện yêu cầu.

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 

Các tài liệu đang ở đây: http://pythonhosted.org/simple-requests/

4

Vì vậy, đó là năm 2016 và chúng tôi có Python 3.4 trở lên với built-in asyncio mô-đun cho không đồng bộ I/O. Chúng tôi có thể sử dụng aiohttp làm ứng dụng khách HTTP để tải xuống nhiều URL song song.

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) 

Nguồn: copy-dán từ http://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

Các vấn đề liên quan