On Sep 19, 2012, at 11:09 AM, Derek Litz wrote: > Do you have a reference I could like at for "bound metadata", not quite sure > what is meant by that.
its this: engine = create_engine(...) metadata.bind = engine > > 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. right, you'd need to close() the session first. the new "transaction" is then dormant, then you deactivate, which prevents it from allowing anything else. > > 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. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. 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.