I'm running into some issues with objects being attached to sessions
that I don't quite understand.

Basically, if I create some objects, add them to a session, commit,
then turf the session (or at least let it fall out of scope), one
expectation I have is that I will still be able to access the basic
properties on the object without a DB connection.  I of course do not
expect the object's attributes to match what is in the database if not
connected, but I still want to access the last known values as if it
were a simple unmapped python object.  In practice, I'm finding that
once an object is added to a session I can't access object attributes
without a connected session.

I also ran into some cases where attribute access was 'mysteriously'
working for some objects and not others after the session was deleted
(or dropped out of scope).  I have since determined that it is because
the associated sessions that I had thought were completely gone had
simply not been garbage collected yet and were still performing their
duties!!

I'm not a gc expert by any means, but thought the lingering session
might have something to do with the weak reference the session has on
contained objects.  I was wrong.  I tried the sessionmaker's
'weak_identity_map = False' option and it had no impact.  What is
confusing is the reverse direction... that the objects still have
usable references to the deleted sessions.

So...
1. Why can't I access simple object properties when the session it was
associated with at one point doesn't exist anymore?
2. Why are 'deleted' sessions still working prior to garbage
collection?

The code example below illustrates both issues.  You can just comment
out the gc.collect() to toggle them.

Any clarification here would be much appreciated.

Russ


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

engine = sa.create_engine("sqlite://")
DeclarativeBase = declarative_base()
Session = orm.sessionmaker(bind = engine)

class MyObj(DeclarativeBase):
    __tablename__ = "bogus"
    id = sa.Column(sa.Integer, primary_key = True, autoincrement =
True)
    name = sa.Column(sa.String, unique = True)

    def __init__(self, Name):
        self.name = Name

DeclarativeBase.metadata.create_all(engine)

def PersistObject(Name):
    obj = MyObj(Name)
    print obj.name   #<-- this works fine prior to session adding
    s = Session()
    s.add(obj)
    s.commit()
    del s #pointless, but trying to accentuate vs scope drop
    return obj

obj1 = PersistObject("Obj1")
obj2 = PersistObject("Obj2")

#Collect the garbage...
import gc
gc.collect() #<-- remove this and the following code runs fine

#If garbage is not collected, the attribute accesses work below...
#If garbage IS collected, access won't work because there is no
session
print obj1.name
print obj2.name

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to