2014-12-10 22 views
15

Asyncio ile birden çok döngüye sahip olmak mümkün mü? Yanıt evet ise bunu nasıl yapabilirim? Benim kullanıldığı durumdur: Ben * Her "alt url listesi" için zaman uyumsuz web sitelerinin bir listeden URL'ler ayıklamak, G/zaman uyumsuz içinde URL'ler ayıklamak içinAsyncio ile çoklu döngüler

Örnek onları sürünebilirim *:

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() 

Bu kodu çalıştırırsam, python ikinci döngü cadıyı başlatmayı denediğinde bir hata yapacağım, bir döngü zaten çalışıyor demektir.

P.S: Modülüm "extractsuburls" web isteği gerçekleştirmek için aiohttp kullanır.

DÜZENLEME:

Eh, bu çözümü deneyin ettik:

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() 

Ama bu hatayı ettik: döngü argüman

herhangi bir fikir Future

kabul etmelisiniz?

cevap

29

sadece extracturls() eşyordamın içinde yield from gather(*subtasks) kullanmak birkaç olay döngüler gerekmez:

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() 

olarak, bitmiş extracturls kadar alt görevler bekliyor olsun sonuçlanır.

+0

Vay canına! Sadece mükemmel. Tam olarak istediğim şey bu. Çok teşekkürler Andrew. – Matt

+0

Sadece bir başka soru Andrew, bu kodla, her bir Görev için bir zaman aşımı nasıl belirleyebilirim? Bir Görev 10'dan fazla harcarsa, bir istisna öldürmek veya yükseltmek istiyorum. Mümkün mü? – Matt

+2

Elbette! Sadece görev coroutine 'wait_for' gibi bir çağrı asyncio.Task (asyncio.wait_for (extractsuburls (url), 10.0)) 'ye kaydırın ' –

İlgili konular