将db connection作为参数传递给方法是一种好习惯吗?

时间:2017-11-06 17:50:21

标签: python postgresql sqlalchemy database-connection

我正在编写Python应用程序以使用SQLAlchemy在Postgres数据库上运行。在settings.py

中指定了数据库信息
DATABASE = {
    'drivername': 'postgres',
    'host': 'xyz.com',
    'port': '5432',
    'username': 'user',
    'password': 'pass',
    'database': 'db_dev'
}

然后我使用创建连接的方法创建了db_connection.py

from sqlalchemy import *
from sqlalchemy.engine.url import URL

from . import settings

def get_engine():
    return create_engine(URL(**settings.DATABASE))

我想让另一个模块db_ops.py具有所有数据库操作func1func2方法,并在主应用程序模块中调用它们

engine = db.connection.get_engine()
db_ops.func1()
db_ops.func2()

这意味着我需要将engine作为参数传递给这些方法。

func1(engine)
func2(engine)

不知怎的,我不喜欢将db连接作为方法参数。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:0)

Engine 连接。您可以将其视为连接池。通常,使用引擎的最自然方式是将其置于全局级别。在您的情况下,您可以将其放在db_connection.py

from sqlalchemy import *
from sqlalchemy.engine.url import URL

from . import settings

engine = create_engine(URL(**settings.DATABASE))

然后,您可以在db_ops模块中导入它:

from db_connection import engine

def func1():
    engine.execute(...)

但是,对于一系列相关查询,您可能希望在单个事务中执行它们,这需要传递实际连接:

with engine.begin() as connection:
    func1(connection)
    func2(connection)

要解决这个问题,我们有scoped_session的概念(同样,在全球范围内):

engine = create_engine(URL(**settings.DATABASE))
Session = scoped_session(sessionmaker(bind=engine))

每次调用Session时,它都会检查当前线程是否已有会话,如果不是,则创建会话,从而无需传递连接:

from db_connection import Session

def func1():
    Session.execute(...)

db_ops个函数的调用方中:

try:
    func1()
    func2()
    Session.commit()
finally:
    Session.remove()