On Mon, Feb 5, 2018 at 8:15 AM, Jacek Blocki <blocki1...@gmail.com> wrote: > Mike, > Thank you for for the tip on _sessions, I think it is worth publishing since > it can make debugging easier. Regarding documentation it will be good to > mention session close() is not like file close() and closed session is just > ready for another transaction. Context manager is typically introduced with > file operations, so python beginner may be left with false assumption closed > session is gone and there is no need to bother with it.
could use more detail I see but if you .close() a Session it's safe to discard. > Separate and external session life cycle perhaps also needs another wording. > SQA user must be aware what session are defined and from which session does > the object come. Objects like queries have information on session > internally, so "separate and external management of session life cycle" > looks impossible for them. you *maintain the start/endpoints* of the session separately and externally but you still make it available to methods that need to use it. A method that works with objects only works with one session at a time so they always know from what session the object came. it's a large subject of general application design but the examples try to steer it that way. if someone doesn't know how to program that way though, it's going to be an uphill climb, they should look at example applications. > BTW are queries the only objects keeping a > reference to session after close()? the Query is a short-term object created from a Session and you shouldn't in the usual case be passing those around to things that last outside of the scope of the Session. You should use a query, get your results, then throw it away. > I've spent quite some time trying to > understand why do I get already attached to session error while all > operations were handled with context manager. "attachment" refers to objects loaded by a session, not the Query object itself. when you call session.close(), those objects are de-associated. you can't get this error unless you start using that Session again (which includes if you use a Query that was created from that Session), and then try to use those newly loaded objects elsewhere. In my application GUI I was > using a query from one session to build dropdown selection and then tried to > modify object attribute with dropdown selected object in another session. > Code demonstrating thy blunder is attached below. > Kind Regards, > Jacek > >>>> from sqlalchemy.orm.session import _sessions >>>> from sqlalchemy import inspect as insp >>>> >>>> #create a session > ... >>>> ses=Session() >>>> # it is empty of course > ... >>>> for i in ses: print i > ... >>>> # query some data > ... >>>> qr=ses.query(MeterReading) >>>> qr.count() > 43 >>>> 43 > 43 >>>> # session is still empty - no object referenced yet > ... >>>> for i in ses: print i > ... >>>> r0 = qr[0] >>>> # now we have one object in ses > ... >>>> for i in ses: print i > ... > <nmeter.appdata.MeterReading object at 0x7f2b16606410> >>>> # close will empty ses > ... >>>> ses.close() >>>> for i in ses: print i > ... >>>> # let's take a picture before we say farewell > ... >>>> ses > <sqlalchemy.orm.session.Session object at 0x7f2b62fec2d0> >>>> insp(r0).session >>>> # replace old ses with brand new from the factory > ... >>>> ses = Session() >>>> ses.add(r0) >>>> # take another object form query qr and add it to session - it will >>>> throw an exception > ... >>>> r1 = qr[1] qr is a Query object. You've closed the Session to which qr is attached but kept qr around, so you are emitting SQL here, using the Session and putting new objects into it. "r1" is now associated with the session you previously closed. >>>> ses.add(r1) > Traceback (most recent call last): > [...] > sqlalchemy.exc.InvalidRequestError: Object '<MeterReading at > 0x7f2b166065d0>' is already attached to session '2' (this is '3') >>>> # because old ses is still there, qr is associated with it and so is r1 as expected > ... >>>> for i in _sessions.items(): print i > ... > (1, <sqlalchemy.orm.session.Session object at 0x7f2b4c1e5c10>) > (2, <sqlalchemy.orm.session.Session object at 0x7f2b62fec2d0>) > (3, <sqlalchemy.orm.session.Session object at 0x7f2b4c1e5b50>) >>>> insp(r0).session > <sqlalchemy.orm.session.Session object at 0x7f2b4c1e5b50> >>>> insp(r1).session > <sqlalchemy.orm.session.Session object at 0x7f2b62fec2d0> >>>> insp(qr).session > <sqlalchemy.orm.session.Session object at 0x7f2b62fec2d0> >>>> >>>> # what if MeterReading has an atribute meter which is a realtionship > ... insp(MeterReading.meter).mapper.class_ > <class 'nmeter.appdata.Meter'> >>>> >>>> # suppose we want to modify r0.meter > ... >>>> qm = insp(r1).session.query(Meter) >>>> qm.count() > 3 >>>> # r0.meter modification with qm will fail > ... >>>> r0.meter = qm[1] > Traceback (most recent call last): > [...] > sqlalchemy.exc.InvalidRequestError: Object '<Meter at 0x7f2b16622250>' is > already attached to session '2' (this is '3') >>>> # obviously it adds meter to r0 session, so we need to disconnect it >>>> form current session > ... m1 = qm[1] >>>> insp(m1).session.expunge(m1) >>>> r0.meter = m1 >>>> # now it works, > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > 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+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- 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+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.