首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Flask和sqlalchemy:处理会话

Flask和sqlalchemy:处理会话
EN

Stack Overflow用户
提问于 2016-02-27 09:03:42
回答 3查看 21.3K关注 0票数 8

我最近开始在我的项目中使用Flask + Sqlalchemy,在离开服务器一天后,我注意到有500个错误。我认为这是由于数据库会话超时,但我不确定。我们是应该为每个请求创建一个新的会话,还是启动Flask应用程序的一对一会话?我把这个放在我的app.py顶部

代码语言:javascript
运行
复制
from sqlalchemy import Column, ForeignKey, Integer, String, create_engine, func, cast, Float 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import relationship,scoped_session,sessionmaker,aliased
engine = createengine(DB_PATH) 
Session = sessionmaker(bind=engine) 
session = Session() 
app = Flask(name_)

然后,对于视图中的所有查询,我执行类似这样的操作:“session.query(表)...”这是不是错了,我应该为每个端点调用建立一个会话吗?

EN

Stack Overflow用户

发布于 2021-01-28 03:10:40

公认的答案有几处错误,尽管无可否认,它应该是有效的。

  1. 它隐含地依赖于threading.local()。虽然对于大多数应用程序来说都很好,但它忽略了安装greenlet的可能性,在这种情况下,本地线程ID是不够的。
  2. 它不必要地使用g。正如评论中指出的那样,scoped_session已经处理了这一部分。

Flask本身不管理线程,这是WSGI服务器的责任。适当地,依赖线程作用域的per the documentation不是存储db会话的推荐方式,尽管它应该工作得很好,因为请求很可能直接与线程相关联。

尤其是,虽然使用线程本地可能很方便,但最好将Session直接与请求相关联,而不是与当前线程相关联。因此,最好根据文档使用自定义作用域,这样我们就可以直接将会话与请求上下文关联起来。这可以使用custom created scope来完成。

来自SQLAlchemy文档的伪代码

代码语言:javascript
运行
复制
from my_web_framework import get_current_request, on_request_end
from sqlalchemy.orm import scoped_session, sessionmaker

Session = scoped_session(sessionmaker(bind=some_engine), scopefunc=get_current_request)

@on_request_end
def remove_session(req):
    Session.remove()

对于SQLAlchemy,要将会话附加到的最干净的对象似乎是应用程序上下文,因为这是与请求直接关联的最高级别变量。下面是关于Flask上下文如何工作的the flask documentation。您可以使用AppContext实例通过_app_ctx_stack访问内部LocalStackThis stackoverlow answer指出了同样的解决方案。_app_ctx_stack.__ident_func__函数非常有用,因为它要么返回线程id,要么调用一个greenlet函数来给出一个可用的标识符。也就是说,flask does appear to use the thread local itself可以做很多事情。我找了又找,但没有找到任何可以保证WSGI服务器为每个请求创建线程的东西。如果谁有这方面的消息来源,我很乐意看看。无论如何,推荐的方法是使用应用程序上下文,这在语义上比依赖与请求具有相同生命周期的线程更清晰。

最后,另一条评论提到使用Flask-SQLAlchemy。虽然这对于大多数项目来说是个好主意,但我不认为它总是有意义。就我个人而言,我希望我的模型定义是用SQLAlchemy定义的,而不是通过Flask-SQLAlchemy。我认为在不久的将来,这些模型很可能(在我的情况下)将在Flask之外使用。我也不想要一个与SQLAlchemy不同的API。句号。虽然我认为它们很可能非常相似,如果不是完全相同的话,但它没有使用SQLAlchemy本身,这是我不喜欢的。我回溯发现了一个得出相同结论的blog from towardsdatascience

尽管如此,我的解决方案看起来与未来的数据科学人员所做的几乎相同。我添加了相关的部分from a repo they published来做这件事。

main.py

代码语言:javascript
运行
复制
from flask import Flask, _app_ctx_stack
from sqlalchemy.orm import scoped_session
from .database import SessionLocal, engine

app = Flask(__name__)
app.session = scoped_session(SessionLocal, scopefunc=_app_ctx_stack.__ident_func__)

@app.teardown_appcontext
def remove_session(*args, **kwargs):
    app.session.remove()

database.py

代码语言:javascript
运行
复制
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

这个主题get相当复杂,所以我欢迎评论,我会更新答案,尽管希望这项研究对其他人有所帮助。

票数 5
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35664436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档