scoped_session(sessionmaker()) or plain sessionmaker() in sqlalchemy?

PythonDjangoOrmSqlalchemyFlask Sqlalchemy

Python Problem Overview


I am using SQlAlchemy in my web project. What should I use - scoped_session(sessionmaker()) or plain sessionmaker() - and why? Or should I use something else?

## model.py
from sqlalchemy import *
from sqlalchemy.orm import *

engine = create_engine('mysql://dbUser:dbPassword@dbServer:dbPort/dbName',
pool_recycle=3600, echo=False)
metadata = MetaData(engine)
Session = scoped_session(sessionmaker())
Session.configure(bind=engine)
user = Table('user', metadata, autoload=True)

class User(object):
pass

usermapper = mapper(User, user)

## some other python file called abc.py
from models import *

def getalluser():
   session = Session()	
   session.query(User).all()
   session.flush()
   session.close()

## onemore file defg.py
from models import *

def updateuser():
   session = Session()	
   session.query(User).filter(User.user_id == '4').update({User.user_lname: 'villkoo'})
   session.commit()
   session.flush()
   session.close()

I create a session = Session() object for each request and I close it. Am I doing the right thing or is there a better way to do it?

Python Solutions


Solution 1 - Python

Reading the documentation is recommended:

>the scoped_session() function is provided which produces a thread-managed registry of Session objects. It is commonly used in web applications so that a single global variable can be used to safely represent transactional sessions with sets of objects, localized to a single thread.

In short, use scoped_session() for thread safety.

Solution 2 - Python

Scoped_session at every method will give you a thread of local session which you cannot obtain beforehand (like at the module level).It's not needed to open a new session in every method, You can use a global session , Create a session only when the global session is not available. i.e you can write a method which returns a session and add it to the init.py inside your package.

Solution 3 - Python

FYI, when using flask-sqlalchemy, the session object provided is by default a scoped session object.

enter image description here

http://flask-sqlalchemy.pocoo.org/2.3/quickstart/#road-to-enlightenment

Solution 4 - Python

I am looking into this myself, but I am not an expert.

My three points are:

  1. SQLAlchemy docs provide a proposed approach using scoped_session, per Mr. Kluev's comment above, at this link: http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#using-thread-local-scope-with-web-applications.
  2. At that web location, the SQLAlchemy docs also say that it is "...strongly recommended that the integration tools provided with the web framework itself be used, if available, instead of scoped_session."
  3. Flask-SQLAlchemy, for example, appears to claim that it takes care of this: http://pythonhosted.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application

Solution 5 - Python

Don't use scoped_session and don't use Flask-SQLAlchemy.

Just use Session = sessionmaker() held in a singleton/service class, and use session = Session() on every HTTP request to guarantee that a fresh connection is provided.

Thread Local storage is clumsy and involves holding state which doesn't play nicely with different web-server threading models. Better to stay stateless. See for example SqlAlchemy's documentation here mentioning not to forget to call .remove() if you are using scoped_session. Will anyone remember to do that?

Below is an excerpt from https://docs.sqlalchemy.org/en/14/orm/contextual.html#using-thread-local-scope-with-web-applications:

> Using the above flow, the process of integrating the Session with the web application has exactly two requirements: > > - Create a single scoped_session registry when the web application first starts, ensuring that this object is accessible by the rest of the application. > > - Ensure that scoped_session.remove() is called when the web request ends, usually by integrating with the web framework’s event system to establish an “on request end” event.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionskoovillView Question on Stackoverflow
Solution 1 - PythontuomurView Answer on Stackoverflow
Solution 2 - PythonAbdul KaderView Answer on Stackoverflow
Solution 3 - PythonNikhil SahuView Answer on Stackoverflow
Solution 4 - PythonSoferioView Answer on Stackoverflow
Solution 5 - PythonBasil MusaView Answer on Stackoverflow