我正在尝试理解代码,该代码大致执行以下操作:
# db.py module
engine = create_engine(DB_URL, pool_timeout=20, pool_recycle=1)
def get_session():
return scoped_session(sessionmaker(bind=engine, expire_on_commit=False))()
def get_base():
base = automap_base()
base.prepare(engine, reflect=True)
return base
base = get_base()
User = base.classes.user
在某些功能中:
# other.py module
from db import get_base, get_session, User
def some_func():
sess = get_session()
# do something with sess and User:
user = sess.query(User).first()
User2 = get_base().classes.user
try:
check = sess.query(User2).first()
except:
sess.rollback()
# do more with sess
sess.commit()
some_func
可以在芹菜任务中调用,但是没有使用greenlets或其他类似的猴子补丁并发技巧。
我想知道,通过重新映射元数据可以实现什么?我的理解是正确的,但是由于作用域会话SQLAlchemy无论如何都会有相同的对象?在这种情况下,会话似乎也一样。
有什么意义?
我对获取相同对象的假设是错误的:
(Pdb) pp user
<sqlalchemy.ext.automap.user object at 0x7f62e1a57390>
(Pdb) pp check
<sqlalchemy.ext.automap.user object at 0x7f62e0e93750>
(Pdb) pp user == check
False
(Pdb) pp user.id
1L
(Pdb) pp check.id
1L
({id
是主键,即唯一)
因此,SQLAlchemy似乎可以使对象分别来自不同的基础。
到目前为止,我最好的猜测是,该技巧允许在当前正在运行的事务之外进行用户存在性测试。
答案 0 :(得分:1)
在大多数情况下,这不是必需的,只会减慢应用程序的速度。在应用程序运行时,数据库模式通常不会经常更改,并且简单的更改无关紧要(请参阅"Data independence")。重做反射等只是人们似乎要做的事情-可能是由于担心使用全局变量。另一方面,在您的示例中,首先似乎在db.py
中仅进行了一次反射以生成全局base
和User
类。
这同样适用于作用域会话注册表。注册表本身旨在为线程本地会话提供服务,因此一直没有必要重新创建它。相反,它应该是应用程序范围内的单例。应该注意的是,使用作用域会话意味着您的应用程序以与其兼容的方式使用线程,换句话说,一个线程应该处理一个作业,例如请求/响应等,从而使应用程序的生命周期得以延长。会话自然绑定到线程的生存期。
由于重新创建了基类和模型类,关于获得相同对象的假设被打破。尽管它们在数据库中代表同一行,但是它们是不同的模型,因此在会话中产生不同的对象。