【发布时间】:2014-08-17 18:39:21
【问题描述】:
SQLAlchemy 建议每个进程使用一个引擎,因为底层 DBAPI 连接不一定可以安全地跨进程使用。
我有全局的 engine 和 session 变量,它们分别被 SQLAlchemy 引擎和会话工厂懒惰地填充。这使得编写依赖的数据库帮助程序变得容易,这些帮助程序可以在运行时调用 get_session() 以在 init_db 为其分配值后使用 session 变量。
这对于让需要访问engine 或session 的助手在初始化engine 或session 之前导入非常有效。但是这种模式使我无法在全局范围内使用engine 和session。
但是,我真正需要做的是:
engine, session = init_db(DB_URL)
...来自调用应用程序/方法,然后将会话注入这些数据库助手。为什么?好吧,我需要每个进程使用一个引擎。我想我在这里需要一种控制模式的反转,但是在想出一些可行的方法时遇到了麻烦(这不涉及在每次调用时将会话传递给助手,这很笨拙,也是最后的手段)。
我想我可以在os.fork() 之后设置引擎。每个进程都以engine=None 开头,然后实例化它。但是engine 在父进程和子进程中具有相同的内存地址。这是有道理的;这就是 Python 的工作原理。
from utils import init_db, engine, DB_URL
import os
def connect():
print('before fork, engine is: {}'.format(id(engine)))
newpid = os.fork()
if newpid == 0:
init_db(DB_URL)
print('child engine is: {}'.format(id(engine))) # id(engine) is equal to below call
else:
init_db(DB_URL)
print('parent engine is: {}'.format(id(engine))) # id(engine) is equal to above call
if __name__ == '__main__':
connect()
根据进程 ID 创建排序池是我的最佳选择吗?如果可能的话,我想使用一个干净的控制模式反转。
NullPool 不会汇集连接,并且可以完成这项工作,但我认为这不是一件好事 - 不断打开和关闭连接似乎很昂贵?
Python 版本:3.4.0
SQLAlchemy 版本:0.9.7
【问题讨论】:
标签: python sqlalchemy inversion-of-control python-3.4