2014-12-10 37 views
15

Có thể có nhiều vòng với asyncio không? Nếu câu trả lời là có, tôi có thể làm như thế nào? trường hợp sử dụng của tôi là: * Tôi lấy url từ một danh sách các trang web trong async * Đối với mỗi "danh sách url phụ", tôi sẽ crawl chúng trong async/Nhiều vòng với asyncio

Ví dụ để trích xuất các url:

import asyncio 
import aiohttp 
from suburls import extractsuburls 

@asyncio.coroutine 
def extracturls(url): 
    subtasks = [] 
    response = yield from aiohttp.request('GET', url) 
    suburl_list = yield from response.text() 
    for suburl in suburl_list: 
     subtasks.append(asyncio.Task(extractsuburls(suburl))) 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(asyncio.gather(*subtasks)) 

if __name__ == '__main__': 
    urls_list = ['http://example1.com', 'http://example2.com'] 
    for url in url_list: 
      subtasks.append(asyncio.Task(extractsuburls(url))) 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(asyncio.gather(*subtasks)) 
    loop.close() 

Nếu tôi thực thi mã này, tôi sẽ gặp lỗi khi python sẽ cố gắng khởi chạy vòng lặp phù thủy thứ hai nói rằng một vòng lặp đã chạy.

P.S: mô-đun "extractsuburls" của tôi sử dụng aiohttp để thực hiện yêu cầu web.

EDIT:

Vâng, tôi đã thử giải pháp này:

import asyncio 
import aiohttp 
from suburls import extractsuburls 

@asyncio.coroutine 
def extracturls(url): 
    subtasks = [] 
    response = yield from aiohttp.request('GET', url) 
    suburl_list = yield from response.text() 
    jobs_loop = asyncio.new_event_loop() 
    for suburl in suburl_list: 
     subtasks.append(asyncio.Task(extractsuburls(suburl))) 
    asyncio.new_event_loop(jobs_loop) 
    jobs_loop.run_until_complete(asyncio.gather(*subtasks)) 
    jobs_loop.close() 

if __name__ == '__main__': 
    urls_list = ['http://example1.com', 'http://example2.com'] 
    for url in url_list: 
      subtasks.append(asyncio.Task(extractsuburls(url))) 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(asyncio.gather(*subtasks)) 
    loop.close() 

Nhưng tôi đã báo lỗi này: đối số vòng lặp phải đồng ý với Future

Bất kỳ ý tưởng?

Trả lời

29

Bạn không cần nhiều vòng sự kiện, chỉ cần sử dụng yield from gather(*subtasks) trong extracturls() coroutine:

import asyncio 
import aiohttp 
from suburls import extractsuburls 

@asyncio.coroutine 
def extracturls(url): 
    subtasks = [] 
    response = yield from aiohttp.request('GET', url) 
    suburl_list = yield from response.text() 
    for suburl in suburl_list: 
     subtasks.append(extractsuburls(suburl)) 
    yield from asyncio.gather(*subtasks) 

if __name__ == '__main__': 
    urls_list = ['http://example1.com', 'http://example2.com'] 
    for url in url_list: 
      subtasks.append(extractsuburls(url)) 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(asyncio.gather(*subtasks)) 
    loop.close() 

Như kết quả bạn nhận được chờ đợi cho đến khi subtasks extracturls xong.

+0

Wow! Hoàn hảo. Đó là chính xác những gì tôi muốn. Cảm ơn rất nhiều Andrew. – Matt

+0

Chỉ cần một câu hỏi khác, với mã này, làm thế nào tôi có thể thiết lập một thời gian chờ cho mỗi nhiệm vụ? Tôi muốn giết hoặc đưa ra một ngoại lệ nếu Nhiệm vụ chi tiêu hơn 10 giây. Có thể không? – Matt

+2

Chắc chắn! Chỉ cần bọc coroutine nhiệm vụ vào 'wait_for' gọi như' asyncio.Task (asyncio.wait_for (extractsuburls (url), 10.0)) ' –

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