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.

Reply via email to