작성
·
44
0
안녕하세요 강사님
강의 열심히 잘 듣고 있습니다.
덕분에 FastAPI에 대한 재미를 더 많이 가지고 있어 감사할 따름입니다.
lifespan 적용하신 강의 관련해서 질문이 있습니다.
저는 현재 환경을 강의 내용과 다르게 진행하고있습니다.
mysql이 아닌 postgresql로 진행하고 있고,
postgresql + asyncpg를 이용하여 비동기 처리를 하고있습니다. lifespan 부분을 적용 시 아래 오류가 발생되고있습니다.
Exception terminating connection <AdaptedConnection <asyncpg.connection.Connection object at 0x00000257982897B0>>
Traceback (most recent call last):
File "D:\personnel\Python\fastapi\fastapi_pguide-main\fastapi_pguide-main\AsyncDB_Handling\.venv\lib\site-packages\sqlalchemy\pool\base.py", line 374, in closeconnection
self._dialect.do_terminate(connection)
File "D:\personnel\Python\fastapi\fastapi_pguide-main\fastapi_pguide-main\AsyncDB_Handling\.venv\lib\site-packages\sqlalchemy\dialects\postgresql\asyncpg.py", line 1117, in do_terminate
dbapi_connection.terminate()
File "D:\personnel\Python\fastapi\fastapi_pguide-main\fastapi_pguide-main\AsyncDB_Handling\.venv\lib\site-packages\sqlalchemy\dialects\postgresql\asyncpg.py", line 910, in terminate
self._connection.terminate()
File "D:\personnel\Python\fastapi\fastapi_pguide-main\fastapi_pguide-main\AsyncDB_Handling\.venv\lib\site-packages\asyncpg\connection.py", line 1515, in terminate
self._abort()
File "D:\personnel\Python\fastapi\fastapi_pguide-main\fastapi_pguide-main\AsyncDB_Handling\.venv\lib\site-packages\asyncpg\connection.py", line 1567, in _abort
self._protocol.abort()
File "asyncpg\\protocol\\protocol.pyx", line 608, in asyncpg.protocol.protocol.BaseProtocol.abort
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\asyncio\selector_events.py", line 686, in abort
self._force_close(None)
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\asyncio\selector_events.py", line 737, in forceclose
self._loop.call_soon(self._call_connection_lost, exc)
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 753, in call_soon
self._check_closed()
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 515, in checkclosed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <asyncpg.connection.Connection object at 0x00000257982897B0>>, which will be terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle.
sys:1: SAWarning: The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <asyncpg.connection.Connection object at 0x00000257982897B0>>, which will be terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle.
위와 같은 오류가 발생되고 있습니다.
방법을 찾아보려 gpt에게 문의도 해봤지만 강의 내용과 동일하거나 또는 starting, shutting (구 FastAPI)방식을 알려주고 있습니다.
나름 응용을 해보겠다고 진행한 건데..
번거로운 질문 드려 죄송합니다.ㅜㅜ
제가 구성한 환경은 이와 같이 진행하였습니다. 참고부탁드리겠습니다.
python =="^3.10"
fastapi == "0.115.4"
uvicorn == "0.32.0"
python-multipart == "0.0.17"
python-dotenv == "1.0.1"
jinja2 == "3.1.4"
sqlalchemy == "2.0.36"
psycopg == {extras = ["binary", "pool"], version = "^3.2.3"}
asyncpg == "^0.30.0"
aiofiles == "24.1.0"
감사합니다.
답변 2
1
안녕하십니까,
잘 듣고 계시다니, 저도 기쁘군요 ^^
이건 저도 셋팅 후에 테스트를 해봐야 해서 시간이 걸릴 것 같습니다. 주말 정도에 답변 드릴 수 있을 것 같습니다.
그리고 수정하신 database.py 와 main.py 를 여기에 올려 주시겠습니까?
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다.
이성민님께서 맞닥뜨리신 문제는 FastAPI 애플리케이션에서 lifespan 사용 중 발생하는 비동기 처리 관련 오류로 보입니다. 주로 AsyncIO와 관련된 오류이며, 이는 보통 데이터베이스 연결을 적절하게 종료하지 못할 때 발생합니다. 아래에서 이 문제를 해결하기 위한 몇 가지 접근법을 제안드리겠습니다.
데이터베이스 연결 관리: 비동기로 데이터베이스와 연결할 때, 연결이 제대로 해제되지 않으면 말씀하신 오류가 발생할 수 있습니다. 따라서 connection pool을 사용하는 경우, 모든 연결이 적절히 닫히도록 확실히 해야 합니다. 이를 위해 아래와 같은 패턴을 사용해볼 수 있습니다.
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import sessionmaker
engine = create_async_engine('postgresql+asyncpg://...')
async_session = sessionmaker(
bind=engine,
expire_on_commit=False,
class_=AsyncSession
)
async def get_db():
async with async_session() as session:
try:
yield session
finally:
await session.close()
lifespan 이벤트 설정: FastAPI에서 lifecycle events를 설정하는 방법을 사용하여 데이터베이스 연결을 생성하고 종료할 수 있습니다.
from fastapi import FastAPI
app = FastAPI()
@app.on_event('startup')
async def startup():
# 데이터베이스 연결 초기화 코드
@app.on_event('shutdown')
async def shutdown():
# 데이터베이스 연결 종료 코드
Connection 확인 및 닫기: 모든 데이터베이스 연결이 쿼리 후에 명확히 닫혀야 합니다. 이를 위해 Session.remove()
메서드를 사용하여 연결을 반환하거나, async with
구문을 사용하여 자동으로 닫히도록 할 수 있습니다.
Event Loop 주의: 오류 메시지에서 ‘Event loop is closed’ 라는 문구가 있는 것으로 보아, 애플리케이션의 이벤트 루프가 정상적으로 처리되지 않을 수 있습니다. 프로그램 종료 시 이벤트 루프가 종료되지 않는지, 다른 곳에서 이벤트 루프를 불필요하게 종료하는지를 확인해보세요.
이 정보가 해결에 도움이 되길 바랍니다. 기존 강의와 연계된 내용이므로 강사님의 답변도 살펴보시면 더 많은 도움이 될 수 있습니다.
다음 링크를 통해 유사한 질문과 답변, 해결방법을 확인해보시는 것도 추천드립니다:
- “lifespan과 이벤트 루프 처리 관련 문제”
저는 질문자님의 이해를 돕고자 유사한 사례와 해결 방법을 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
네 강사님,
코드 올려드립니다.
오늘 하루 즐거운 하루 보내세요!
감사합니다.
main.py
database.py