我是Python新手,我正在开发一个FastAPI & 小淘气应用程序。我想要显式管理数据库连接池,所以根据FastAPI的框架集成文档,我使用启动/关闭事件。
database = PooledSqliteDatabase('foobar.db', autoconnect=False, stale_timeout=60)
with database:
database.create_tables([models.Foobar])
app = FastAPI()
app.include_router(foobar_router)
@app.on_event("startup")
def startup():
database.connect()
@app.on_event("shutdown")
def shutdown():
if not database.is_closed():
database.close()
问题是,这些事件并不对应于“在收到请求时打开连接,然后在返回响应时关闭连接”,而是当整个应用程序启动和停止时。更重要的是,我不明白为什么我会得到“错误,数据库连接没有打开”。当我访问我的路由器中的数据库时,它还应该在那个时候打开吗?只有当我将async
添加到我的路由中时,它才会起作用。
我想我可以切换到适当的“在请求之前/之后”中间件,但此时我想知道我的方法是否完全错误。
编辑:我试过使用中间件,但尽管这一功能不出所料,但我仍然存在“错误,数据库连接未打开”的问题。除非我把async
加到我的路线上。
@app.middleware("http")
async def with_database(request: Request, call_next):
with database:
response = await call_next(request)
return response
发布于 2022-09-14 14:20:31
注意,在异步环境中,您的池可能不会像预期的那样工作。Peewee的连接模型,包括池,是围绕每个连接的线程建立的.使用异步连接时,连接是池化的,但是由于所有的连接都运行在同一个线程中,所以您的所有协同器都将共享相同的连接。这对标准线程或gevent代码(将本地线程修补为绿色线程本地)没有任何问题。
尽管如此,我不使用FastAPI,但从它们的(疯狂的) sqlalchemy中推断,如果您想避免使用每个请求的中间件,可以尝试以下方法:
from fastapi import Depends, FastAPI, HTTPException
app = FastAPI()
database = PooledSqliteDatabase('foobar.db', autoconnect=False, stale_timeout=60)
with database:
database.create_tables([models.Foobar])
def ensure_connection():
database.connect()
try:
yield database
finally:
database.close()
@app.post("/users/", ...)
def create_user(..., database=Depends(ensure_connection)):
...
不过,我认为每个请求的中间件可能更容易实现。考虑到我在评论开始时的警告,我强烈建议您分析您的应用程序并验证它是否正确地使用了连接--这很可能(这将取决于您何时屈服于事件循环)--尽管如此。
https://stackoverflow.com/questions/73718206
复制相似问题