Reputation: 253
sqlalchemy suggests the transaction pattern for sessions:
# myapp.py
from contextlib import contextmanager
engine = create_engine('sqlite:////tmp/test.db')
Session = sessionmaker(bind=engine)
@contextmanager
def session_scope():
"""Provide a transactional scope around a series of operations."""
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
...
with session_scope() as session:
# do stuff
Furthermore, I have noticed that for web applications, session_scope
should be used:
# my_scoped_app.py
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:////tmp/test.db')
db_session = scoped_session(sessionmaker(bind=engine))
...
# Some app definition
...
@app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
Since I want to scale Flask beyond a single-thread, is it safe to use the first pattern? In other words, does it matter whether I implement some class like
from myapp import session_scope()
class Foo(object):
def do_stuff(self, args):
with session_scope() as session:
do_more_stuff(session, args)
versus
from my_scoped_app import db_session:
class Foo(object):
def do_stuff(self, args):
session = db_session()
do_more_stuff(session, args)
session.commit()
session.close()
Ignoring the differences in exception handling.
Upvotes: 2
Views: 2275
Reputation: 23
What i found is that the first approach will create new session each time you call it. The second approach will firstly check if session for current thread exists and if not will also create new session.
Second approach is alot cleaner when dealing with session in different modules within same thread.
So technicly you're getting the same from both within single request while using it.
Upvotes: 1