- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在阅读有关在 Twisted 应用程序上下文中使用 SQLAlchemy 的 ORM 的一些资料。有很多信息需要消化,所以我在将所有部分放在一起时遇到了一些麻烦。到目前为止,我收集了以下绝对真理:
scoped_session
为我们提供了一种将 session 限制到给定线程的方法。换句话说,我确信通过使用 scoped_session
,我不会将 session 传递给其他线程(除非我明确地这样做,但我不会这样做)。我还收集到一些与延迟/急切加载相关的问题,一种可能的方法是将 ORM 对象与 session 分离,并在更改线程时将它们重新附加到另一个 session 。我对细节很模糊,但我也得出结论,scoped_session
使其中的许多点都没有实际意义。
我的第一个问题是我的上述结论是否严重错误。
除此之外,我还设计了这种方法,希望它能令人满意。
我首先创建一个 scoped_session
对象...
Session = scoped_session(sessionmaker(bind=_my_engine))
...然后我将从上下文管理器中使用它,以便优雅地处理异常和清理:
@contextmanager
def transaction_context():
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.remove() # dispose of the session
现在我需要做的就是在延迟到单独线程的函数中使用上述上下文管理器。我拼凑了一个装饰器来让事情变得更漂亮:
def threaded(fn):
@wraps(fn) # functools.wraps
def wrapper(*args, **kwargs):
return deferToThread(fn, *args, **kwargs) # t.i.threads.deferToThread
return wrapper
这是我打算如何使用整个 shebang 的示例。下面是一个使用 SQLAlchemy ORM 执行数据库查找的函数:
@threaded
def get_some_attributes(group):
with transaction_context() as session:
return session.query(Attribute).filter(Attribute.group == group)
我的第二个问题是这种方法是否可行。
编辑: Here是关于上下文管理器中意外错误的相关问题。
最佳答案
现在我正在处理这个确切的问题,我想我找到了解决方案。
确实,您必须将所有数据库访问功能推迟到一个线程。但是在您的解决方案中,您在查询数据库后删除了 session ,因此所有结果 ORM 对象都将被分离,您将无法访问它们的字段。
你不能使用 scoped_session 因为在 Twisted 中我们只有一个 MainThread(除了在 deferToThread 中工作的东西)。但是,我们可以将 scoped_session
与 scopefunc
一起使用。
在 Twisted 中有一个很棒的东西叫做 ContextTracker
:
provides a way to pass arbitrary key/value data up and down a call stack without passing them as parameters to the functions on that call stack.
在方法 render_GET
中我扭曲的网络应用程序中,我设置了一个 uuid
参数:
call = context.call({"uuid": str(uuid.uuid4())}, self._render, request)
然后我调用 _render
方法来完成实际工作(使用数据库、渲染 html 等)。
我这样创建 scoped_session
:
scopefunc = functools.partial(context.get, "uuid")
Session = scoped_session(session_factory, scopefunc=scopefunc)
现在,在 _render
的任何函数调用中,我都可以获得 session :
Session()
在 _render
结束时,我必须执行 Session.remove()
来删除 session 。
它适用于我的网络应用程序,我认为它可以用于其他任务。
这是一个完全独立的示例,展示了它们如何协同工作。
from twisted.internet import reactor, threads
from twisted.web.resource import Resource
from twisted.web.server import Site, NOT_DONE_YET
from twisted.python import context
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
import uuid
import functools
engine = create_engine(
'sqlite:///test.sql',
connect_args={'check_same_thread': False},
echo=False)
session_factory = sessionmaker(bind=engine)
scopefunc = functools.partial(context.get, "uuid")
Session = scoped_session(session_factory, scopefunc=scopefunc)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
Base.metadata.create_all(bind=engine)
class TestPage(Resource):
isLeaf = True
def render_GET(self, request):
context.call({"uuid": str(uuid.uuid4())}, self._render, request)
return NOT_DONE_YET
def render_POST(self, request):
return self.render_GET(request)
def work_with_db(self):
user = User(name="TestUser")
Session.add(user)
Session.commit()
return user
def _render(self, request):
print "session: ", id(Session())
d = threads.deferToThread(self.work_with_db)
def success(result):
html = "added user with name - %s" % result.name
request.write(html.encode('UTF-8'))
request.finish()
Session.remove()
call = functools.partial(context.call, {"uuid": scopefunc()}, success)
d.addBoth(call)
return d
if __name__ == "__main__":
reactor.listenTCP(8888, Site(TestPage()))
reactor.run()
我打印出 session 的 ID,您可以看到它对于每个请求都是不同的。如果您从 scoped_session
构造函数中删除 scopefunc
并同时执行两个请求(将 time.sleep 插入 work_with_db
),您将为此获得一个公共(public) session 两个请求。
The scoped_session object by default uses threading.local() as storage, so that a single Session is maintained for all who call upon the scoped_session registry, but only within the scope of a single thread
这里的一个问题是在 twisted 中我们只有一个线程来处理所有请求。这就是为什么我们必须创建自己的 scopefunc
,这将显示请求之间的差异。
另一个问题是,twisted 没有将上下文传递给回调,我们必须包装回调并将当前上下文发送给它。
call = functools.partial(context.call, {"uuid": scopefunc()}, success)
我仍然不知道如何让它与 defer.inLineCallback
一起工作,我在我的代码中无处不在。
关于python - 这是从 Twisted 进行线程化 SQLAlchemy 查询的可接受方式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21076105/
我正在尝试创建一个使用 UUID 作为主键的用户模型: from src.db import db # SQLAlchemy instance import sqlalchemy_utils impo
在 sqlalchemy 中,我试图合并表,然后使用 WHERE 和 ORDER_BY 创建别名 有点像 SELECT * FROM ( SELECT [TABLE_ONE].[SOME_ID]
我正在使用 SQL Alchemy(通过 Flask_sqlalchemy)将 Python 字典列表插入到 Postgres 数据库中。 其中一个表是所有唯一项目的列表(表 1),而第二个是与某个项
This source详细说明如何使用关联代理创建具有 ORM 对象值的 View 和对象。 但是,当我附加一个与数据库中现有对象匹配的值(并且所述值是唯一的或主键)时,它会创建一个冲突的对象,因此我
SQLAlchemy Core和SQLAlchemy ORM的目的有什么区别? 最佳答案 顾名思义,ORM是一个对象关系映射器:其目的是将数据库关系表示为Python对象。 核心是查询构建器。其目的是
带有ForeignKey的Column是否自动创建索引? 还是我需要手动添加index=True? some_field = Column(Integer, ForeignKey(SomeModel.
我有一个主数据库,每个客户自己的数据库连接存储在其中。 因此,每个客户端都使用2个db:main和它自己的db,必须确定其连接 对于每个http调用。我如何使用flask-sqlalchemy扩展名执
当我仅对类进行继承时,它才起作用 class User(Base): __tablename__ = ’users’ id = Column(Integer, primary_key=
从用户的角度来看,SQLAlchemy 的查询日志似乎有点过于冗长,有时甚至有点神秘: 2015-10-02 13:51:39,500 INFO sqlalchemy.engine.base.Engi
我正在尝试使用 wtforms.ext.sqlalchemy QuerySelectMultipleField 显示复选框列表,但我无法在 GET 的表单上显示模型数据。 这是我的models.py
我想为查询返回一个中继连接。使用标准的 graphene-sqlalchemy 你可以这样做: class Query(graphene.ObjectType): node = relay.N
我在 centos 7.5 虚拟机上部署了最新的 Airflow ,并将 sql_alchemy_conn 和 result_backend 更新到 postgresql 实例上的 postgres
我想将多个项目插入到一个表中,并在发生冲突时更新该表。这是我想出的以下内容 from sqlalchemy.dialects.postgresql import insert meta = MetaD
我有以下模型: class Item(Base): a = relationship() b = relationship() c = relationship() d
我有 presto 和 superset 设置。 presto 运行良好,可以通过命令访问: ./app/hadoop/setjdk8.sh;bin/presto-cli --server http:
我一直在寻找一种在 sqlalchemy 中使用 tsvector 的方法(就像 INTEGER 等其他方法一样),但到目前为止我还不清楚如何做到这一点。我读过可以使用 UserDefinedType
我正在使用 sqlalchemy(现在使用 sqlite,但稍后可能会改变)来构建一个数据库,其中插入的顺序和 rowids 很重要。我基本上有以下几点: class Message(Base):
给定一个对象,我想知道如何知道它是否是 sqlalchemy 映射模型的实例。 通常,我会使用 isinstance(obj, DeclarativeBase)。但是,在这种情况下,我没有可用的 De
我已经通读了查询文档,如果有办法从查询中获取表名,就看不到任何地方 - 例如如果我有 q = query(Users) ,我可以得到Users从 q 退出? 最佳答案 请注意,像您这样的事件简单查询可
我不确定如何定义create schema foo迁移?我的模型如下所示(我正在使用Flask-Migrate): class MyTable(db.Model): __tablename__
我是一名优秀的程序员,十分优秀!