본문 바로가기

오류모음집/python

RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-1_0'.

반응형

 

 

발생 경위 : 비동기 함수 3개와 함께 다음과 같이 실행 시 발생하였음 

async def crawl_and_insert(target: str, count: int, driver_class, source: str) -> None:
    loop = asyncio.get_running_loop()
    with ThreadPoolExecutor(max_workers=3) as executor:
        # run_in_executor를 통해 크롤링을 비동기적으로 실행
        data_list = await loop.run_in_executor(
            executor, lambda: driver_class(target=target, count=count).news_collector()
        )

    if data_list:  # 데이터가 있을 때만 처리
        await mongo_main(data_list, source)  # MongoDB에 데이터 삽입


async def crawling_data_insert_db(target: str, count: int):
    tasks = [
        crawl_and_insert(target, count, AsyncNaverNewsParsingDriver, "naver"),
        crawl_and_insert(target, count, AsyncDaumNewsParsingDriver, "daum"),
        crawl_and_insert(target, count, AsyncGoogleNewsParsingDriver, "google"),
    ]

    await asyncio.gather(*tasks)  # 모든 크롤링 작업을 동시에 수행


# 비동기 함수 실행
asyncio.run(crawling_data_insert_db("BTC", 3))

 

 

발생 이유: ThreadPoolExecutor 스레드에 이벤트 루프가 접근했을때 발생 

 

스레드는 고유한 실행 환경을 가지고 있기 떄문에 asyncio 간 이벤트 루프가 스레드간 공유가 발생이 안됨 

asyncio 비동기 기능을 사용하려고 할때, 현재 스레드에 이벤트 루프가 설정되어 있지 않다면 오류가 발생함 

 

 

해결 방안 

async def crawl_and_insert(target: str, count: int, driver: Callable, source: str) -> None:
    loop = asyncio.get_running_loop()
    
    def run_driver() -> UrlDictCollect:
        # 새 이벤트 루프를 생성하고 실행
        new_loop = asyncio.new_event_loop()
        asyncio.set_event_loop(new_loop)
        return new_loop.run_until_complete(driver(target=target, count=count).news_collector())

    with ThreadPoolExecutor(max_workers=3) as executor:
        # run_in_executor를 통해 크롤링을 비동기적으로 실행
        data_list = await loop.run_in_executor(executor, run_driver)

    if data_list:  # 데이터가 있을 때만 처리
        await mongo_main(data_list, source)  # MongoDB에 데이터 삽입

 

loop.run_until_complete()는 비동기 코루틴이 완료될 때까지 이벤트 루프를 실행하므로,

호출한 스레드 내에서 해당 코루틴의 실행 순서는 보장

여러 스레드에서 이벤트 루프를 사용하는 경우에는 각 스레드가 독립적인 이벤트 루프를 가지고 있으므로,

스레드 간의 작업 실행 순서는 보장되지 않음

반응형