I don't know if the following traceback, from my Pylons project, will shed light on this. But I have fixed the error that I'm about to mention, and it was not what it appeared, which makes me wonder if SqlAlchemy has a bug in its error reporting (or on the other hand maybe there's just something I don't understand in the process).
I was chasing down an error that said "Connection Already Closed" and having a tough time figuring it out. I read the FAQ on the subject and several of Mike's replies to people's posts. All of this existing material spoke about leaving a connection open too long, and other related issues with connection pooling and recycling. I was pretty sure that wasn't my problem. I even rebooted the machine that my project lives on, and the same error was happening on first access to the database after rebooting. Not merely restarting the paster webserver. Oddly, the error only happened on a call to session.flush() right after update() was called on an object. In other parts of my little CRUD app, I was able to create new values and save them just fine. It was only in the attempt to update an existing row that the error was happening. Finally after enough hair loss, I stopped poring over the tracebacks shown in the Pylons error response, and went directly to the paster debug logs. Hmm! What was actually happening was that a foreign key relationship was being violated (or i guess you could say just not satisfied) by the value I was trying to save (update). The foreign key error message went to the log where I wasn't looking, because I typically only look there if the in-browser Pylons error response is absent or otherwise hung up. Meanwhile for some reason the ultimate result was showing up as Connection Already Closed. So maybe the underlying Foreign Key error resulted in the connection closing, and something in the way SA handled that led to the Connection error, and I only saw the latter because I hadn't thought to look for an error beneath the error. Here's the trace from the Pylons error handler in the browser: URL: http://127.0.0.1:5000/FVal/update/1160 File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\error.py', line 245 in respond app_iter = self.application(environ, detect_start_response) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\wsgiapp.py', line 315 in __call__ return self.app(environ, start_response) File 'h:\\python25\\lib\\site-packages\\Beaker-0.9.3-py2.5.egg\\beaker\ \middleware.py', line 74 in __call__ return self.app(environ, start_response) File 'h:\\python25\\lib\\site-packages\\Beaker-0.9.3-py2.5.egg\\beaker\ \middleware.py', line 145 in __call__ return self.wrap_app(environ, session_start_response) File 'h:\\python25\\lib\\site-packages\\Routes-1.7.2-py2.5.egg\\routes\ \middleware.py', line 104 in __call__ response = self.app(environ, start_response) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\wsgiapp.py', line 95 in __call__ response = self.dispatch(controller, environ, start_response) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\wsgiapp.py', line 237 in dispatch return controller(environ, start_response) File 'H:\\msys\\1.0\\home\\Eric\\rentals\\rentals\\lib\\base.py', line 30 in __call__ return WSGIController.__call__(self, environ, start_response) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\controllers\\core.py', line 164 in __call__ response = self._dispatch_call() File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\controllers\\core.py', line 120 in _dispatch_call response = self._inspect_call(func) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\controllers\\core.py', line 79 in _inspect_call result = func(**args) File 'H:\\msys\\1.0\\home\\Eric\\rentals\\rentals\\controllers\ \FVal.py', line 118 in update return render('/ShowFVal.mako') File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\templating.py', line 343 in render format=format, namespace=kargs, **cache_args) File 'h:\\Python25\\lib\\site-packages\\pylons-0.9.6.1-py2.5.egg\ \pylons\\templating.py', line 228 in render **options) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \ext\\turbogears.py', line 49 in render return template.render(**info) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \template.py', line 114 in render return runtime._render(self, self.callable_, args, data) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \runtime.py', line 287 in _render _render_context(template, callable_, context, *args, **_kwargs_for_callable(callable_, data)) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \runtime.py', line 304 in _render_context _exec_template(inherit, lclcontext, args=args, kwargs=kwargs) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \runtime.py', line 337 in _exec_template callable_(context, *args, **kwargs) File 'H:\\msys\\1.0\\home\\Eric\\rentals\\data\\templates\ \base.mako.py', line 28 in render_body context.write(unicode(next.body())) File 'h:\\python25\\lib\\site-packages\\mako-0.1.10-py2.5.egg\\mako\ \runtime.py', line 193 in <lambda> return lambda *args, **kwargs:callable_(self.context, *args, **kwargs) File 'H:\\msys\\1.0\\home\\Eric\\rentals\\data\\templates\ \ShowFVal.mako.py', line 36 in render_body feature = c.FVal.feature File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\attributes.py', line 44 in __get__ return self.impl.get(instance._state) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\attributes.py', line 225 in get value = callable_() File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\strategies.py', line 470 in __call__ return q.get(ident) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\query.py', line 154 in get return self._get(key, ident, **kwargs) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\query.py', line 975 in _get return q.all()[0] File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\query.py', line 780 in all return list(self) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\query.py', line 841 in __iter__ return self._execute_and_instances(context) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\query.py', line 844 in _execute_and_instances result = self.session.execute(querycontext.statement, params=self._params, mapper=self.mapper, instance=self._refresh_instance) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\orm\\session.py', line 605 in execute return self.__connection(engine, close_with_result=True).execute(clause, params or {}) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\engine\\base.py', line 846 in execute return Connection.executors[c](self, object, multiparams, params) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\engine\\base.py', line 897 in execute_clauseelement return self._execute_compiled(elem.compile(dialect=self.dialect, column_keys=keys, inline=len(params) > 1), distilled_params=params) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\engine\\base.py', line 906 in _execute_compiled context = self.__create_execution_context(compiled=compiled, parameters=distilled_params) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\engine\\base.py', line 952 in __create_execution_context self._handle_dbapi_exception(e, kwargs.get('statement', None), kwargs.get('parameters', None), None) File 'h:\\python25\\lib\\site-packages\\sqlalchemy-0.4.3-py2.5.egg\ \sqlalchemy\\engine\\base.py', line 944 in _handle_dbapi_exception raise exceptions.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect) InterfaceError: (InterfaceError) connection already closed None [{'{ANON 27984048 param}': 159}] ==== END OF TRACE ========== ## AND... here's what was in the logs in the shell window I unfortunately wasn't watching: 01:35:22,233 DEBUG [pylons.templating] Render called with [] args and {} keyword args 01:35:22,233 WARNI [sqlalchemy.pool.QueuePool.0x..10] Error closing cursor: cursor already closed Traceback (most recent call last): File "h:\Python25\lib\logging\__init__.py", line 744, in emit msg = self.format(record) File "h:\Python25\lib\logging\__init__.py", line 630, in format return fmt.format(record) File "h:\Python25\lib\logging\__init__.py", line 418, in format record.message = record.getMessage() File "h:\Python25\lib\logging\__init__.py", line 288, in getMessage msg = msg % self.args File "h:\Python25\lib\site-packages\pylons-0.9.6.1-py2.5.egg\pylons \util.py", line 94, in __repr__ value_repr = repr(value) File "H:\msys\1.0\home\Eric\rentals\rentals\model\__init__.py", line 402, in __repr__ Feature.by_id(self.feature_id).name, File "H:\msys\1.0\home\Eric\rentals\rentals\model\__init__.py", line 203, in by_id result = Session.query(Feature).filter_by(id=id).one() File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\orm\query.py", line 827, in one ret = list(self[0:2]) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\orm\query.py", line 841, in __iter__ return self._execute_and_instances(context) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\orm\query.py", line 844, in _execute_and_instances result = self.session.execute(querycontext.statement, params=self._params, mapper=self.mapper, instance=self._refresh_instance) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\orm\session.py", line 605, in execute return self.__connection(engine, close_with_result=True).execute(clause, params or {}) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 846, in execute return Connection.executors[c](self, object, multiparams, params) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 897, in execute_clauseelement return self._execute_compiled(elem.compile(dialect=self.dialect, column_keys=keys, inline=len(params) > 1), distilled_params=params) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 909, in _execute_compiled self.__execute_raw(context) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 918, in __execute_raw self._cursor_execute(context.cursor, context.statement, context.parameters[0], context=context) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 962, in _cursor_execute self._handle_dbapi_exception(e, statement, parameters, cursor) File "h:\python25\lib\site-packages\sqlalchemy-0.4.3-py2.5.egg \sqlalchemy\engine\base.py", line 944, in _handle_dbapi_exception raise exceptions.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect) OperationalError: (OperationalError) insert or update on table "feature_values" violates foreign key constraint "fk > tokens" DETAIL: Key (value)=(2007) is not present in table "tokens". 'SELECT features.itemtype_id AS features_itemtype_id, features.name AS features_name, features.featuretype AS features_featuretype, features.ordinal AS features_ordinal, features.attachment AS features_attachment, features.id AS features_id, features.parent_id AS features_parent_id, features.dynattach AS features_dynattach \nFROM features \nWHERE features.id = %(features_id_1)s ORDER BY features.id \n LIMIT 2 OFFSET 0' {'features_id_1': 159} .. so it was only because I forgot to satisfy a foreign key before calling commit(). But I was held back for a long time in discovering that underlying problem, because I was digging all over the SA world trying to figure out why I was having this "Connection Already Closed" trouble. Moral of the story? Always watch the logs. But I submit this case here, in case it might indicate that some part of SqlAlchemy's error reporting / exception handling might need some adjusting. Available information out there seemed to unanimously agree that I was going to have to study up on connection lifetimes etc etc, when actually that was fully barking up the wrong tree in this case. - Eric --~--~---------~--~----~------------~-------~--~----~ 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 [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---