Sqlalchemy:使用装饰器为多个函数提供线程安全的会话

Seb*_*erk 5 python session multithreading sqlalchemy decorator

我正在研究类似这里的东西(带有 sqlalchemy 的多线程应用程序),所以我明白,我应该为每个 db-query 创建一个新会话。

我想知道,如果为每个需要 DB 访问的方法使用装饰器是否有意义,或者是否存在使用这种方法的陷阱。装饰器是按照此处的最后一个示例构建

def dbconnect(func):
    def inner(*args, **kwargs):
        session = Session()  # with all the requirements
        try:
            func(*args, session=session, **kwargs)
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            session.close()
    return inner

@dbconnect
def some_function(some, arguments, session)
    session.query(...) # no commit, close, rollback required

some_function("many", "different_arguments") 
#session is not required, since provided by decorator
Run Code Online (Sandbox Code Playgroud)

这将使为任何函数提供线程安全的 DB 访问变得相当容易,而无需实现整个 try-except-finally-stuff 冗余,但我不确定,如果这种方法是故障安全的和 pythonic,或者是否存在其他最佳实践。

ukr*_*utt 7

我认为在这里使用 a 是有意义的scoped_session,也许像这样:

session_factory = sessionmaker(bind=some_engine)
Session = scoped_session(session_factory)

def dbconnect(func):
    def inner(*args, **kwargs):
        session = Session()  # (this is now a scoped session)
        try:
            func(*args, **kwargs) # No need to pass session explicitly
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            Session.remove()  # NOTE: *remove* rather than *close* here
    return inner

@dbconnect
def some_function(some, arguments):
    session = Session()
    # 'session' is  now a handle to the *same* session as in the decorator
    session.query(...) # no commit, close, rollback required

some_function("many", "different_arguments") 
#session is not required, since provided by decorator
Run Code Online (Sandbox Code Playgroud)

(警告:未经测试)

  • 删除是在一个finally 块中,它“保证”它会被调用。 (2认同)

Jas*_*n S 2

添加参数的装饰器很有趣,但可能很棘手。定义的参数列表现在与调用者实际使用的不同步。如果您显式传递session=something给它,它将引发异常(尽管您可以在装饰器中检查)

您还需要至少添加一个functools.wraps(当然,这是简短的示例代码)。

事务是上下文管理器的一个很好的用例。请参阅多线程 sqlalchemy web 应用程序中推荐的scoped_session 使用模式是什么?对此有一个想法。