2014-12-10 2 views
15

asyncio를 사용하여 여러 루프를 가질 수 있습니까? 응답이 예인 경우 어떻게해야합니까? 내 사용 사례는 다음과 같습니다 내가 * 각 "서브 URL 목록"에 대한 비동기에서 웹 사이트 목록에서 URL을 추출, 내가/비동기에서 URL을 추출하는asyncio가있는 다중 루프

예 크롤링 것이다 * :

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

이 코드를 실행하면 파이썬이 두 번째 루프를 시작하려고 할 때 오류가 발생합니다. 마녀는 루프가 이미 실행 중이라고 말합니다.

추신 : 내 모듈 "extractsuburls"는 aiohttp를 사용하여 웹 요청을 수행합니다.

편집 :

음,이 솔루션을 시도했습니다

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

을하지만이 오류를했습니다 : 루프 인수는

어떤 생각 미래

에 동의해야 하는가?

답변

29

당신은 extracturls() 코 루틴에 yield from gather(*subtasks)를 사용하여 여러 이벤트 루프가 필요하지 않습니다 :

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

으로 당신이 완료 extracturls 때까지 하위 기다리고 얻을 결과.

+0

와우! 완벽 해. 그것은 내가 원하는 것입니다. Andrew에게 감사드립니다. – Matt

+0

또 다른 질문 Andrew,이 코드를 사용하여 각 작업에 대해 시간 제한을 설정하려면 어떻게해야합니까? 작업이 10 초 이상 걸리는 경우 예외를 발생 시키거나 제거하려고합니다. 가능한가? – Matt

+2

예! 그냥''asyncio.Task (asyncio.wait_for (extracteduburls (url), 10.0))'wait_for' 호출로 작업 코 루틴을 감싸십시오. –