When to create new sessions?

2 views
Skip to first unread message

rint...@googlemail.com

unread,
Apr 7, 2009, 6:07:16 PM4/7/09
to sqlalchemy
Hey Everyone,

I'm new to SQLAlchemy (used to using Django's ORM but need to switch)
and there's just one thing I'm struggling with, which is when am I
supposed to create Sessions? I am of course creating "scoped
sessions". I feel like a real dunce for not being able to get my head
around it.

Do I create one per-request and pass it around? That just doesn't feel
quite right to me. Or can I create them at module-level when I need
them? Also, is it okay to call commit() more than once on the same
session? On a per-function basis even (seems like an awful lot of
boilerplate code in each function though… surely not?!)

Sorry if I'm rambling, I just don't get when I'm supposed to
instantiate a new session =) I know this is probably something really
simple that most people get instantly.

Kind regards

Michael Bayer

unread,
Apr 7, 2009, 11:53:12 PM4/7/09
to sqlal...@googlegroups.com

On Apr 7, 2009, at 6:07 PM, rint...@googlemail.com wrote:

>
> Hey Everyone,
>
> I'm new to SQLAlchemy (used to using Django's ORM but need to switch)
> and there's just one thing I'm struggling with, which is when am I
> supposed to create Sessions? I am of course creating "scoped
> sessions". I feel like a real dunce for not being able to get my head
> around it.
>
> Do I create one per-request and pass it around? That just doesn't feel
> quite right to me. Or can I create them at module-level when I need
> them?

per-request is the most natural approach. The point of the
"scopedsession" is that you can use it as a "global" object, there's
no need to pass it around. It automatically routes operations to a
thread-local session. I'm sure django does something similar. the
chapter on sessions includes a discussion on integrating scopedsession
within a web application, you should check it out.


> Also, is it okay to call commit() more than once on the same
> session?

absolutely.


> On a per-function basis even (seems like an awful lot of
> boilerplate code in each function though… surely not?!)

depending on what you're doing , this may or may not be appropriate.
boilerplate can be cut down using a decorator, such as:

@commits
def do_some_stuff(...):
....

the decorator:

def commits(fn):
def go(*args, **kw):
try:
return fn(*args, **kw)
Session.commit()
except:
Session.rollback()
raise
return go

Session is a scopedsession which can be declared at the module level.


Diez B. Roggisch

unread,
Apr 8, 2009, 10:12:59 AM4/8/09
to sqlal...@googlegroups.com

Not to be to nitpicky... but this commit is never reached. And dangling
transactions can be very irritating.


I'd go for this (untetsted)

def transaction(f)
def _wrapper(*args, **kwargs):
commit = True
try:
return f(*args, **kwargs)
except:
commit = False
finally:
(session.commit if commit else session.rollback)()


Diez

Bobby Impollonia

unread,
Apr 8, 2009, 11:14:36 PM4/8/09
to sqlal...@googlegroups.com
Now the decorator swallows exceptions silently. You have to reraise
the exception after rolling back like Michael did. I believe the
correct form is:

def transaction(f):
def wrapper(*args, **kwargs):
try:
value = f(*args, **kwargs)
except:
session.rollback()
raise
else:
session.commit()
return value
return wrapper

Diez B. Roggisch

unread,
Apr 9, 2009, 5:39:50 AM4/9/09
to sqlal...@googlegroups.com
On Thursday 09 April 2009 05:14:36 Bobby Impollonia wrote:
> Now the decorator swallows exceptions silently. You have to reraise
> the exception after rolling back like Michael did. I believe the
> correct form is:

Darn.. you're right of course :)

Diez

Reply all
Reply to author
Forward
0 new messages