Python 为什么需要重新进行自动映射?(炼金术)

Python 为什么需要重新进行自动映射?(炼金术),python,sqlalchemy,introspection,Python,Sqlalchemy,Introspection,我试图理解代码,它大致完成以下任务: # 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.

我试图理解代码,它大致完成以下任务:

# 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可以在芹菜任务中调用,但是没有使用greenlet或其他类似的猴子补丁并发技巧

我想知道,通过重新映射元数据可以实现什么?我的理解正确吗,那么由于作用域会话,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似乎将对象从不同的基础分开


到目前为止,我最好的猜测是,这个技巧允许在当前正在运行的事务之外进行用户存在性测试。

大多数情况下,它不是必需的,只是降低了应用程序的速度。在应用程序运行时,数据库模式通常不会经常更改,简单的更改应该无关紧要。重做反思等只是人们似乎在做的事情——可能是因为害怕使用globals。另一方面,在您的示例中,在db.py中,似乎只执行一次反射来生成全局基类和用户类

这同样适用于作用域会话注册表。注册表本身是用来服务线程本地会话的,所以一直重新创建它是没有意义的。相反,它应该是一个应用程序范围的单例。应该注意,使用作用域会话意味着您的应用程序以与之兼容的方式使用线程,或者换句话说,单个线程应该处理单个作业,例如请求/响应等,以便会话的生存期自然绑定到线程的生存期


您关于由于重新创建基类和模型类而导致相同对象中断的假设。虽然它们代表数据库中的同一行,但它们是不同的模型,因此在会话中生成不同的对象。

谢谢-这是非常有用的信息。我又加了一句话来解释原因。希望人们能找到这种问答,停止这种低效的做法。那么,重做反射的正当理由是什么呢?可能是在一些长时间运行的应用程序中,这些应用程序必须在不停止的情况下升级,或者诸如此类。我自己在这方面的经验是有限的,所以很难想出经常重做反射的用例。这并不是说没有用例。