使用FastAPI和SQLAlchemy制作API时,当数据库(SQLite)存储在内存中时,我会遇到奇怪的行为,而这在作为文件存储时不会发生。
型号:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
class Thing(Base):
__tablename__ = "thing"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
我创建了两个全局引擎对象。一个以数据库为文件,另一个作为内存数据库:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
args = dict(echo=True, connect_args={"check_same_thread": False})
engine1 = create_engine("sqlite:///db.sqlite", **args)
engine2 = create_engine("sqlite:///:memory:", **args)
Session1 = sessionmaker(bind=engine1)
Session2 = sessionmaker(bind=engine2)
我创建了我的FastAPI应用程序和一个将对象添加到数据库中的路径:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def foo(x: int):
with {1: Session1, 2: Session2}[x]() as session:
session.add(Thing(name="foo"))
session.commit()
我的主要任务是模拟请求并检查一切是否正常:
from fastapi.testclient import TestClient
if __name__ == "__main__":
Base.metadata.create_all(engine1)
Base.metadata.create_all(engine2)
client = TestClient(app)
assert client.get("/1").status_code == 200
assert client.get("/2").status_code == 200
thing
表是在engine1中创建并提交的,与engine2一样。第一个请求成功地将"foo“插入到工程1的数据库(存储为文件),但第二个请求引发"sqlite3.OperationalError”,声称“没有这样的表: thing”。
为何两者之间有不同的行为?为什么内存中的数据库声称表不存在,即使SQLAlchemy日志显示create语句已成功运行并已提交?
发布于 2022-11-22 18:42:03
文档在下面的https://docs.sqlalchemy.org/en/14/dialects/sqlite.html#using-a-memory-database-in-multiple-threads中解释了这一点
要使用:
:数据库,在多线程场景中,必须在线程之间共享相同的连接对象,因为数据库只存在于该连接的范围内。StaticPool实现将全局维护单个连接,check_same_thread标志可以作为False传递给Pysqlite。
它还展示了如何获得预期的行为,因此在您的情况下
from sqlalchemy.pool import StaticPool
args = dict(echo=True, connect_args={"check_same_thread": False}, poolclass=StaticPool)
https://stackoverflow.com/questions/74536228
复制