Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python/Flask best practice for service layer

Tags:

python

flask

I'm a little new to Python ( I come from a Java/C++ background ). I've been playing around with Flask for web development. My question relates somewhat to dependecy injection and thread safety. In the Java/Spring word you would have a Controller that has a Service say UserService injected into it. And when you have say a addUser endpoint it would call the userService.addUser(someData).

If I want to do the same in Python/Flask is it best practice to just have a file called UserService with functions like addUser(), deleteUser() etc and just straight call them with UserService.addUser(), UserService.deleteUser() and is this thread safe? Or should I have a new instance of User service in each endpoint?

like image 843
imrank1 Avatar asked May 20 '13 15:05

imrank1


People also ask

Is FastAPI better than Flask?

FastAPI surpasses Flask in terms of performance, and it is one of the fastest Python web frameworks. Only Starlette and Uvicorn are faster. Because of ASGI, FastAPI supports concurrency and asynchronous code by declaring the endpoints. For concurrent programming, Python 3.4 introduced Async I/O.

Can we implement RESTful web services using Flask?

"Flask allows Python developers to create lightweight RESTful APIs."

Why is Flask built-in server not suitable for production?

While lightweight and easy to use, Flask's built-in server is not suitable for production as it doesn't scale well. Some of the options available for properly running Flask in production are documented here.


1 Answers

As with all things thread-related, the question is "did you make it thread-safe"?

If your user service looks like this:

# 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)

Then, assuming an even remotely sane implementation of some.package.database it will be thread safe. If, on the other hand, you do something like this:

# 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. ...

Now, including db = database.connect() at the top of each of your service methods is very un-DRY. You can avoid that issue by wrapping up your connection-specific work in a decorator (for example):

def provide_db(func):

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

    return new_function

Then you could do this:

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

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

# ... etc. ...
like image 171
Sean Vieira Avatar answered Sep 18 '22 06:09

Sean Vieira