error related to setting attribute to same value twice

814 views
Skip to first unread message

lars van gemerden

unread,
Sep 2, 2013, 11:01:36 AM9/2/13
to sqlal...@googlegroups.com
Hi all,

I have a one-to-one and many-to-one relationship (with an association table in the middle; Report.author-assoctable-Person.reports; why the table in the middle, you might ask, well it's a long story) and i am setting the author on a specific Report twice to the same value. This gives the following error:

           InvalidRequestError: Can't attach instance <person at 0x36a9350>; another instance with key (<class 'models.data.classes.person'>, (2,)) is already present in this session.

The first time i set the author, it works and if i change the author it works as well.

This seems i little strange to me, why not be able to set the attribute to the same value twice?

Otherwise i have to check whether the new and old values are equal (which through the peculiarties of my code is somewhat wastefull) 

Cheers, Lars 

Simon King

unread,
Sep 2, 2013, 11:39:44 AM9/2/13
to sqlal...@googlegroups.com
I think the message is actually telling you that you have 2 different
instances of your "person" class with the same primary key. SQLAlchemy
uses an identity map to ensure that a particular row in the database
is only identified by a single instance within a particular session.
If you violate that assumption (eg. by loading one instance of
"person" from the database, then creating another instance and setting
its primary key), you will get errors like this.

Does that sound plausible?

Simon

Lars van Gemerden

unread,
Sep 2, 2013, 1:56:21 PM9/2/13
to sqlal...@googlegroups.com
Well, from the message yes, but i am not setting any primary keys manually, so where could the second instance come from?

CL

====================================
Lars van Gemerden
la...@rational-it.com
+31 6 26 88 55 39
====================================
> --
> You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/bkm3-nB6d1o/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
> To post to this group, send email to sqlal...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.

Simon King

unread,
Sep 2, 2013, 2:23:32 PM9/2/13
to sqlal...@googlegroups.com
Without knowing your application it's very difficult to know...

Is there any chance that the second object is already associated with a different session? Perhaps from a different thread, or retrieved from a cache or something similar?

Producing a standalone test script would help in diagnosing the problem.

Simon
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.

lars van Gemerden

unread,
Sep 2, 2013, 2:58:53 PM9/2/13
to sqlal...@googlegroups.com
Yes I know the question was a bit vague, but i couldn't think of a simple way to show some code. A test case would probably require some major surgery; I'll consider it though.

It is possible that the second instance is associated with a different session, i'd have to check. What actually happens if you add the same instance to a second session?

CL

Simon King

unread,
Sep 2, 2013, 3:18:11 PM9/2/13
to sqlal...@googlegroups.com
Dunno, let's try it:

import sqlalchemy as sa
import sqlalchemy.orm as saorm
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Person(Base):
__tablename__ = 'people'
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
name = sa.Column(sa.String(20))

if __name__ == '__main__':
engine = sa.create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = saorm.sessionmaker(bind=engine)

# Create our first session and use it to add a Person to the database
sess1 = Session()
sess1.add(Person(name='lars'))
sess1.commit()
sess1.close()

# Retrieve our Person from the database again.
person = sess1.query(Person).first()

# Now try to add that instance to a second session
sess2 = Session()
sess2.add(person)
sess2.commit()


Output:

Traceback (most recent call last):
...
sqlalchemy.exc.InvalidRequestError: Object '<Person at 0x10c9f5790>' is already attached to session '1' (this is '2')

Looks very similar to your error message. I'm using SA 0.8.0 - it looks like the message is slightly different in your version.

The correct thing to do in this case is to use "session.merge" to create a copy of the object, attached to the new session. If you change the last few lines of the script above to:

sess2 = Session()
merged = sess2.merge(person)
sess2.add(merged)

...it works fine.

Hope that helps,

Simon

lars van gemerden

unread,
Sep 3, 2013, 5:15:04 AM9/3/13
to sqlal...@googlegroups.com
I am getting that same error (not the original one). For the moment i've solved the problem in a different way, but it might pop up again. I'll keep merge in mind (i've run into the" is already attached to session" before).

Thank you, Lars 

Simon King

unread,
Sep 3, 2013, 5:38:09 AM9/3/13
to sqlal...@googlegroups.com
I realised after I sent that script that I wasn't reproducing quite
the same situation. I should have loaded the person from the database
in sess2 as well, before trying to add the instance from sess1. In
other words, change the end of the test script to say:

sess2 = Session()
dupe = sess2.query(Person).first()
sess2.add(person)
sess2.commit()

So sess2 now contains an instance representing that database row. The
error message is now:

AssertionError: A conflicting state is already present in the identity
map for key (<class '__main__.Person'>, (1,))

...which is still not quite the same as your error message. What
version of SQLAlchemy are you using? (The above was from 0.8.2)

Simon

lars van Gemerden

unread,
Sep 3, 2013, 2:57:47 PM9/3/13
to sqlal...@googlegroups.com
My version is 0.7.5 (thought i was on 8 already), i will look at updating!

The error sounds similar, I'll get back on this after i do (after some research to find out if updating is a good idea right now)

Cheers, Lars


Reply all
Reply to author
Forward
0 new messages