Pyramid with SQLAlchemy:范围内或非范围内的数据库会话

Pyramid with SQLAlchemy: scoped or non-scoped database session

对于旧版本的金字塔,sqlalchemy 会话的设置是使用 scooped_session 完成的,类似于

DBSession = scoped_session(
    sessionmaker(
        autoflush=True,
        expire_on_commit=False,
        extension=zope.sqlalchemy.ZopeTransactionExtension()
    )

但是我看到较新的教程以及金字塔 docs 'promotes' sqlalchemy 没有 threadlocals,其中 DBSession 附加到请求对象。

'old' 方式是否损坏?无线程本地化的优势是什么?

我在其他几位贡献者的帮助下带头进行了这一转变,他们在博客 [1] 中介绍了一些优势。它基本上归结为遵循金字塔哲学,即可以编写不需要任何全局变量的应用程序。这在编写可重用、可组合的代码时非常重要。它使您的代码的依赖关系(api 表面)清晰,而不是让随机函数依赖于您的数据库,尽管它们的函数签名/成员变量没有暴露这些依赖关系。这也使得测试代码变得更容易,因为您不必担心线程局部变量。使用全局变量,您需要追踪哪些模块可能持有对它们的引用并修补它们以使用新对象。如果没有全局变量,您只需传入要使用的对象,代码就会使用它们,就像函数的任何其他参数或对象的状态一样。

很多人抱怨必须将他们的数据库传递给大量函数。这是一种气味,仅表示您没有很好地设计 api。很多时候,您可以将事物构造为一个对象,该对象根据请求创建一次,并将句柄存储为 self.dbsession 之类的东西,对象上的每个方法现在都可以访问它。

[1] https://metaclassical.com/testing-pyramid-apps-without-a-scoped-session/