Do you have a reference I could like at for "bound metadata", not quite 
sure what is meant by that.

Anyways, I tried out both methods:

session.bind = None, doesn't stop the session from being used at all (it 
does break get_bind() though, humorously).

session.transaction._deactivate() does "work" in a sense (by itself: see 
below).  I can't query with the session until I rollback() or close().  The 
MAJOR drawback of this is the connection is held on to by the session.  The 
session is normally very good at releasing the connection back to the pool 
as soon as possible and I'd like to keep this behavior as normal.

Oh, nice, I'll leave above as reference, but I just tried closing the 
session PRIOR to calling session.transaction._deactivate() and it manages 
create a session in the state that I want.

for s in sessions:
    s.query(User).first()
    s.close()
    s.transaction._deactivate()

Yes, it'd certainly be nice to have a public API for something like this (I 
do feel the "close" communicates it works in this fashion, simply because 
of how close works with a connection ie. it's closed and you can't use it 
anymore, but changing THAT API may be too much to ask.) 

Adding a ".deactivate" method to the session that makes it unusable from 
that point on sounds like a good idea.

Output from interpretor below:

+------------------+

session.query(User).first()
Out[100]: <ntb.common.orm.user.User at 0x2a11d10>

session.bind = None

session.query(User).first()
Out[102]: <ntb.common.orm.user.User at 0x2a11d10>

session.get_bind()
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (15, 0))

---------------------------------------------------------------------------
UnboundExecutionError                     Traceback (most recent call last)
/home/dlitz/Dev/ntb/<ipython-input-103-7acbb6e607dc> in <module>()
----> 1 session.get_bind()

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.pyc in 
get_bind(self, mapper, clause)
    937             else:
    938                 raise sa_exc.UnboundExecutionError(
--> 939                     "This session is not bound to a single Engine 
or "
    940                     "Connection, and no context was provided to 
locate "
    941                     "a binding.")

UnboundExecutionError: This session is not bound to a single Engine or 
Connection, and no context was provided to locate a binding.

+------------------+

And using session.transaction._deactivate() (by itself)

+------------------+

len(sessions)
Out[9]: 15

for s in sessions:
    s.query(User).first()
    s.transaction._deactivate()

session = session_maker()

session.query(User).first()

---------------------------------------------------------------------------
TimeoutError                              Traceback (most recent call last)
/home/dlitz/Dev/ntb/<ipython-input-13-fbb31c44fc53> in <module>()
----> 1 session.query(User).first()

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.pyc in 
first(self)
   2105             ret = list(self)[0:1]
   2106         else:
-> 2107             ret = list(self[0:1])
   2108         if len(ret) > 0:
   2109             return ret[0]

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.pyc in 
__getitem__(self, item)
   1999                 return list(res)[None:None:item.step]
   2000             else:
-> 2001                 return list(res)
   2002         else:
   2003             if item == -1:

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.pyc in 
__iter__(self)
   2174         if self._autoflush and not self._populate_existing:
   2175             self.session._autoflush()
-> 2176         return self._execute_and_instances(context)
   2177 
   2178     def _connection_from_session(self, **kw):

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.pyc in 
_execute_and_instances(self, querycontext)
   2187                         mapper = self._mapper_zero_or_none(),
   2188                         clause = querycontext.statement,
-> 2189                         close_with_result=True)
   2190 
   2191         result = conn.execute(querycontext.statement, self._params)

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.pyc in 
_connection_from_session(self, **kw)
   2178     def _connection_from_session(self, **kw):
   2179         conn = self.session.connection(
-> 2180                         **kw)
   2181         if self._execution_options:
   2182             conn = conn.execution_options(**self._execution_options)

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.pyc in 
connection(self, mapper, clause, bind, close_with_result, **kw)
    727 
    728         return self._connection_for_bind(bind, 
--> 729                                         
close_with_result=close_with_result)
    730 
    731     def _connection_for_bind(self, engine, **kwargs):

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.pyc in 
_connection_for_bind(self, engine, **kwargs)
    731     def _connection_for_bind(self, engine, **kwargs):
    732         if self.transaction is not None:
--> 733             return self.transaction._connection_for_bind(engine)
    734         else:
    735             return engine.contextual_connect(**kwargs)

/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.pyc in 
_connection_for_bind(self, bind)
    264                         "given Connection's Engine")
    265             else:
--> 266                 conn = bind.contextual_connect()
    267 
    268         if self.session.twophase and self._parent is None:

/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.pyc in 
contextual_connect(self, close_with_result, **kwargs)
   2474 
   2475         return self._connection_cls(self, 
-> 2476                                     self.pool.connect(),
   2477                                     
close_with_result=close_with_result,
   2478                                     **kwargs)

/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.pyc in connect(self)
    222         """
    223         if not self._use_threadlocal:
--> 224             return _ConnectionFairy(self).checkout()
    225 
    226         try:

/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.pyc in 
__init__(self, pool)
    385         self._echo = _echo = pool._should_log_debug()
    386         try:
--> 387             rec = self._connection_record = pool._do_get()
    388             conn = self.connection = 
self._connection_record.get_connection()
    389             rec.fairy = weakref.ref(

/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.pyc in _do_get(self)
    725                             "QueuePool limit of size %d overflow %d 
reached, "
    726                             "connection timed out, timeout %d" %
--> 727                             (self.size(), self.overflow(), 
self._timeout))
    728 
    729             if self._overflow_lock is not None:

TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection 
timed out, timeout 30

+---------------+

And using close() before transaction._deactivate()

+----------------+

for s in sessions:
    s.query(User).first()
    s.close()
    s.transaction._deactivate()
    
len(sessions_2)
Out[49]: 15

for s in sessions_2:
    s.query(User).first()

"YAY! :)"

Out[51]: 'YAY! :)'

+---------------+

Thanks again for the prompt response.

Derek

On Tuesday, September 18, 2012 6:09:24 PM UTC-5, Michael Bayer wrote:
>
>
> On Sep 18, 2012, at 11:38 AM, Derek Litz wrote: 
>
> > A session when closed, commited, or rolled back, releases the database 
> connection it acquired from the pool.  The session can grab a new 
> connection later on as needed.  Also, many objects a session can create 
> have a reference to this session, and the session could be used elsewhere. 
>  This leads to the potential of doing database access where one would have 
> thought no database access was going on, even if I'm clearly not re-using 
> the session object anywhere else directly. 
> > 
> > ie.  I call session.close() before passing my data to a template engine, 
> but one of the objects was a query object (by mistake), which when iterated 
> over will query the database while rendering the template. 
> > 
> > Is there a standard way I could stop the session object from grabbing 
> another connection to the database and throw an exception instead?   If not 
> I'd be open to non-standard ways as well :) 
>
> You can reset the ".bind" on the Session to None, but this assumes that 
> you aren't using "bound metadata". 
>
> As far as non-standard, I've never tried this but if you manually 
> "deactivate" the transaction, should work: 
>
>         session.transaction._deactivate() 
>
> This can certainly be a public API at some point if it works for you. 
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/ALrv8F32NH8J.
To post to this group, send email to sqlalchemy@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