인프런 커뮤니티 질문&답변

그린 이들님의 프로필 이미지
그린 이들

작성한 질문수

파이썬 동시성 프로그래밍 : 데이터 수집부터 웹 개발까지 (feat. FastAPI)

프로젝트 마무리

RuntimeWarning: Enable tracemalloc to get the object allocation traceback

작성

·

859

·

수정됨

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

 

# app 폴더 아래 main.py
@app.post("/collect", response_class=HTMLResponse)
async def collect(request: Request):
    brandlist = BrandList()
    brands = await brandlist.run()
    oy_models = []
    for brand in brands:
        oy_model = BrandListModel(
            code=brand["code"],
            brand=brand["brand"],
            collection_time=brand["time"],
            status=brand["status"],
        )
        oy_models.append(oy_model)

    await mongodb.engine.save_all(oy_models)

    return templates.TemplateResponse(
        "./index.html",
        {"request": request, "title": "수집기", "brands": brands},
    )


# app 폴더 아래 spcrper.py
class BrandList:
    URL = "https://www.#######.co.kr"

    def unit_url(self):
        url = f"{self.URL}/store/main/getBrandList.do"
        return url

    async def fetch(self):
        async with aiohttp.ClientSession() as session:
            async with session.get(self.unit_url()) as response:
                soup = BeautifulSoup(await response.text(), "html.parser")
                area_info = soup.select("a[data-ref-onlbrndcd]")
                branddics = []
                for info in area_info:
                    code = info["data-ref-onlbrndcd"]
                    name = info.text
                    collectiontime = date.today()
                    item = [i["code"] for i in branddics]

                    if code in item:
                        pass
                    else:
                        branddic = {
                            "code": f"{code}",
                            "brand": f"{name}",
                            "time": f"{collectiontime}",
                            "status": "Old",
                        }
                        branddics.append(branddic)
            await session.close()
            return branddics

    def run(self):
        return asyncio.run(self.fetch())

 

안녕하세요. 강사님. scraper.py 는 terminal에서 값을 잘 가져오고 있습니다. server.py에서 구동 시, 아래와 같은 error가 나오는데 원인을 찾지 못해서요 ㅠ

 

RuntimeError: asyncio.run() cannot be called from a running event loop

C:\Users\user\Desktop\Project_Scraper\venv\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py👎 RuntimeWarning: coroutine 'BrandList.fetch' was never awaited

RuntimeWarning: Enable tracemalloc to get the object allocation traceback

 

코드 리뷰 좀 부탁드리겠습니다.

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

님의 문제는 RuntimeError: asyncio.run() cannot be called from a running event loopRuntimeWarning: coroutine 'BrandList.fetch' was never awaited 가 발생하는 것으로 보입니다. 이는 asyncio가 이미 실행 중인 이벤트 루프 안에서 asyncio.run()을 호출하려고 할 때 발생하는 문제입니다. FastAPI와 같은 비동기 프레임워크에서는 이미 이벤트 루프가 실행 중이므로, asyncio.run()을 직접 사용할 수 없습니다.

코드에서 BrandList.run() 메소드 내에서 asyncio.run(self.fetch())를 호출하는 부분이 문제의 원인입니다. 대신, 이미 실행 중인 이벤트 루프 내에서 비동기 함수를 호출하려면 해당 함수를 await 키워드와 함께 호출해야 합니다. 그러나 BrandList.run() 메소드는 비동기 함수가 아니므로, 이 메소드 자체를 비동기 함수로 바꿔 await를 사용할 수 있게 해야 합니다.

수정할 수 있는 방안은 다음과 같습니다:
- BrandList.run() 메소드를 비동기 함수로 변경합니다.
- fetch() 호출 시 await를 사용합니다.

수정된 BrandList 클래스는 아래와 같이 될 수 있습니다:

class BrandList:
    URL = "https://www.#######.co.kr"

    def unit_url(self):
        url = f"{self.URL}/store/main/getBrandList.do"
        return url

    async def fetch(self):
        async with aiohttp.ClientSession() as session:
            async with session.get(self.unit_url()) as response:
                soup = BeautifulSoup(await response.text(), "html.parser")
                ...
            await session.close()
            return branddics

    async def run(self):
        return await self.fetch()

그리고 collect 함수 내에서 brandlist.run()을 호출할 때 await 키워드를 사용해야 합니다.

brands = await brandlist.run()

이렇게 수정하면, 기존에 발생했던 오류를 해결할 수 있을 것입니다.

그린 이들님의 프로필 이미지
그린 이들

작성한 질문수

질문하기