sqlalchemy.exc.InvalidRequestError: Object '<Foo at 0x23b0690>' is already attached to session '29012560' (this is '30924944')

1,759 views
Skip to first unread message

erictho...@gmail.com

unread,
May 30, 2009, 1:56:44 AM5/30/09
to sqlalchemy
I've spent a day scratching my head over this now so I figure it's
time to seek some outside help. I'm using Elixir and my setup looks
like this:

entities.py:

class Foo(Entity):
# fields ...


db_module.py:

import elixir
from elixir import session as elixir_session

def connect_engine():
elixir.metadata.bind = 'connection info'


main.py:

from entities import Foo
from db_module import *

def main()
connect_engine()
# a bunch of stuff
foo = Foo()

Upon reaching the instantiation of Foo, my code blows up with the
error message in the subject. Now I realize this is often caused by
threading issues - multiple threads, each with their own Session,
trying to touch an entity without first merging that entity into the
thread's local session. But my application is single-threaded and to
the best of my knowledge I'm not creating any new sessions other than
the ScopedSession that was created when I imported elixir. Even if I
had attempted to create several sessions via elixir_session(), my
understanding is that I would have been returned the same session
because I haven't changed threads and elixir by default uses a
ScopedSession. So why is Foo winding up in a new session (and how did
it already get attached to my current session)? I haven't passed any
options regarding the session in my entity definitions.

On a somewhat related note, why does Session have so many class
methods? It's perplexing to me that I can do things like
elixir_session.query(Foo).all() and also elixir_session().query
(Foo).all(). I've tried digging through Elixir's entity.py and
SQLAlchemy's session.py but I didn't get much out of my first couple
of reads.

-Eric

Michael Bayer

unread,
May 31, 2009, 10:50:11 AM5/31/09
to sqlal...@googlegroups.com

On May 30, 2009, at 1:56 AM, erictho...@gmail.com wrote:

> Upon reaching the instantiation of Foo, my code blows up with the
> error message in the subject. Now I realize this is often caused by
> threading issues - multiple threads, each with their own Session,
> trying to touch an entity without first merging that entity into the
> thread's local session. But my application is single-threaded and to
> the best of my knowledge I'm not creating any new sessions other than
> the ScopedSession that was created when I imported elixir. Even if I
> had attempted to create several sessions via elixir_session(), my
> understanding is that I would have been returned the same session
> because I haven't changed threads and elixir by default uses a
> ScopedSession.

that is all correct.

> So why is Foo winding up in a new session (and how did
> it already get attached to my current session)? I haven't passed any
> options regarding the session in my entity definitions.

I can't see anything here which would cause this. A frequent cause
of this confusion is when a library makes use of the
ScopedSession.mapper method which has the effect of objects being
automatically added to a session without the need to say
session.add(object) - but again confusion would only occur here if
there is more han one session in use.

> On a somewhat related note, why does Session have so many class
> methods? It's perplexing to me that I can do things like
> elixir_session.query(Foo).all() and also elixir_session().query
> (Foo).all(). I've tried digging through Elixir's entity.py and
> SQLAlchemy's session.py but I didn't get much out of my first couple
> of reads.

its the ScopedSession you're dealing with. The methods are not
class methods, as ScopedSession is instantiated. for every public
Session method, the ScopedSession implements a proxying method which
will invoke that method upon a Session pulled from a threading.local()
object. To access the Session stored in the threading.local()
directly, ScopedSession implements __call__().


Gaetan de Menten

unread,
Jun 2, 2009, 4:44:25 AM6/2/09
to sqlal...@googlegroups.com
On Sun, May 31, 2009 at 16:50, Michael Bayer <mik...@zzzcomputing.com> wrote:
>
>
> On May 30, 2009, at 1:56 AM, erictho...@gmail.com wrote:
>
>> Upon reaching the instantiation of Foo, my code blows up with the
>> error message in the subject.  Now I realize this is often caused by
>> threading issues - multiple threads, each with their own Session,
>> trying to touch an entity without first merging that entity into the
>> thread's local session.  But my application is single-threaded and to
>> the best of my knowledge I'm not creating any new sessions other than
>> the ScopedSession that was created when I imported elixir.  Even if I
>> had attempted to create several sessions via elixir_session(), my
>> understanding is that I would have been returned the same session
>> because I haven't changed threads and elixir by default uses a
>> ScopedSession.
>
> that is all correct.
>
>> So why is Foo winding up in a new session (and how did
>> it already get attached to my current session)?   I haven't passed any
>> options regarding the session in my entity definitions.
>
> I can't see anything here which would cause this.    A frequent cause
> of this confusion is when a library makes use of the
> ScopedSession.mapper method which has the effect of objects being
> automatically added to a session without the need to say
> session.add(object) - but again confusion would only occur here if
> there is more han one session in use.

FWIW, this is the case with Elixir by default. You can turn that
behavior off if you want though. That explains why your new object
gets attached to the current session as soon as you instanciate your
class. I have no idea why it is using a different session though.


--
Gaëtan de Menten
http://openhex.org

Reply all
Reply to author
Forward
0 new messages