Python/Flask服务层的最佳实践

imr*_*nk1 13 python flask

我是Python的新手(我来自Java/C++背景).我一直在玩Flask进行网页开发.我的问题在某种程度上与依赖注射和线程安全有关.在Java/Spring中,你会有一个控制器,它有一个服务说UserService注入其中.当你说一个addUser端点时,它会调用userService.addUser(someData).

如果我想在Python/Flask中做同样的事情,那么最好只使用一个名为UserService的文件,其中包含addUser(),deleteUser()等函数,并使用UserService.addUser(),UserService.deleteUser()直接调用它们.这个线程安全吗?或者我应该在每个端点都有一个新的用户服务实例?

Sea*_*ira 21

与线程相关的所有事情一样,问题是"你是否使它成为线程安全的"?

如果您的用户服务如下所示:

# user_service.py
from some.package import database

def add_user(user_information=None):
    db = database.connect()
    db.insert(user_information)

def update_user(user_information=None):
    db = database.connect()
    db.update(user_information["user_id"], user_information)

def delete_user(user_id=None):
    db = database.connect()
    db.delete(user_id)
Run Code Online (Sandbox Code Playgroud)

然后,假设一个甚至远程理智的实现some.package.database将是线程安全的.另一方面,如果你做这样的事情:

# bad_user_service.py
from some.package import database

# Shared single connection
# Probably *not* thread safe
db = database.connect()

def add_user(user_information=None):
    db.insert(user_information)

# ... etc. ...
Run Code Online (Sandbox Code Playgroud)

现在,包括db = database.connect()在您的每个服务方法的顶部非常非干.您可以通过在装饰器中包装特定于连接的工作来避免该问题(例如):

def provide_db(func):

    @functools.wraps(func)
    def new_function(*args, **kwargs):
        db = database.connect()
        return func(db, *args, **kwargs)

    return new_function
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

# user_service.py
from your.data.layer import provide_db

@provide_db
def add_user(db, user_information=None):
    db.insert(user_information)

# ... etc. ...
Run Code Online (Sandbox Code Playgroud)