为什么我在 FastAPI 和 peewee 应用程序中获得"Error, database connection not opened"?



我是Python的新手,正在开发FastAPI&peewee应用程序。我想明确管理数据库连接池,因此根据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

请注意,在异步环境中,您的池可能无法正常工作。Peewee的连接模型,包括池,是围绕每个连接的一个线程构建的。使用async,连接是池化的,但由于所有东西都在同一个线程中运行,所以所有的协同程序都将共享同一个连接。这对于标准线程或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)):
...

不过,我认为按请求中间件可能更容易实现。鉴于我在评论开头的警告,我强烈建议您分析您的应用程序,并验证它是否正确使用了连接——但很可能不是(这将取决于您何时屈服于事件循环(。

相关内容

最新更新