SQLAlchemy transaction errors do not return proper trace (Python 2.7)

In my current User model, I have a "name" field that cannot be null.

I am trying to create a user object and add it to the DBSession provided by Pyramid and pass it with a transaction, for example.

with transaction.manager: u = models.User() models.DBSession.add(u) 

For those not using Pyramid, DBSession:

 DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) 

Now, in my transaction above, I have a verification problem - I need to assign a name to the User, but I did not. However, instead of receiving the error message “You need to assign a username!”, I get the following:

 <ipython-input-5-47d9c0e393f7> in <module>() 2 u = models.User() ----> 3 models.DBSession.add(u) 4 /home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction/_manager.pyc in __exit__(self, t, v, tb) 118 def __exit__(self, t, v, tb): 119 if v is None: --> 120 self.commit() 121 else: 122 self.abort() /home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction/_manager.pyc in commit(self) 109 """ See ITransactionManager. 110 """ --> 111 return self.get().commit() 112 113 def abort(self): /home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction/_transaction.py in commit(self) 276 tb = None 277 try: --> 278 t, v, tb = self._saveAndGetCommitishError() 279 self._callAfterCommitHooks(status=False) 280 reraise(t, v, tb) /home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction/_transaction.py in _saveAndGetCommitishError(self) 300 import pdb 301 pdb.set_trace() --> 302 traceback.print_stack(sys._getframe(1), None, ft) 303 # Append the stack entries from here down to the exception. 304 traceback.print_tb(tb, None, ft) /usr/lib/python2.7/traceback.py in print_stack(f, limit, file) 267 except ZeroDivisionError: 268 f = sys.exc_info()[2].tb_frame.f_back --> 269 print_list(extract_stack(f, limit), file) 270 271 def format_stack(f=None, limit=None): /usr/lib/python2.7/traceback.py in print_list(extracted_list, file) 23 ' File "%s", line %d, in %s' % (filename,lineno,name)) 24 if line: ---> 25 _print(file, ' %s' % line.strip()) 26 27 def format_list(extracted_list): /usr/lib/python2.7/traceback.py in _print(file, str, terminator) 11 12 def _print(file, str='', terminator='\n'): ---> 13 file.write(str+terminator) 14 15 TypeError: 'unicode' does not have the buffer interface 

I found that the problem is that somewhere there is a version of python version 2 vs 3 shown here TypeError: 'str' does not support the buffer interface . I know that SQLAlchemy supports python 3+, and therefore, when a problem may arise.

Please note that if I execute my transaction correctly, there will be no errors.

Is there a way around this problem without overwriting the code in traceback.py?

+7
traceback sqlalchemy
source share
1 answer

The error you see is not (at least directly) caused by SQLAlchemy, but caused by a combination of SQLAlchemy, IPython and the way you try to use transaction . It will disappear if you follow the recommended use of these tools.

Denial of responsibility. The following is not a recommended way to use the cloud session and ZopeTransactionExtension in Pyramids, but I wanted to stay as close as possible to your provided code.

Put this in a file and run it from virtualenv with SQLAlchemy installed and you will see the correct error message from SQLAlchemy:

 from sqlalchemy import types from sqlalchemy import create_engine from sqlalchemy.schema import Column from zope.sqlalchemy import ZopeTransactionExtension from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, scoped_session Base = declarative_base() class User(Base): __tablename__ = 'user' name = Column(types.String, primary_key=True) def pretend_view(request): """Pretend view in a Pyramid application using pyramid_tm""" import transaction user = User() with transaction.manager: DBSession.add(user) return user if __name__ == '__main__': engine = create_engine('sqlite://') global DBSession DBSession = scoped_session( sessionmaker(extension=ZopeTransactionExtension())) DBSession.configure(bind=engine) Base.metadata.bind = engine Base.metadata.create_all() #import IPython; IPython.embed() pretend_view("dummy request") 

sqlalchemy.exc.IntegrityError: (IntegrityError) NOT NULL constraint failed: user.name u'INSERT INTO user DEFAULT VALUES' () this exception: sqlalchemy.exc.IntegrityError: (IntegrityError) NOT NULL constraint failed: user.name u'INSERT INTO user DEFAULT VALUES' ()

If you run IPython and run pretend_view, you will get an Unicode error message.

Proper use of pyramid_tm

Now, if you want to see the correct error message in IPython, use the "correct" session!

There is usually no reason to use transaction explicitly in your code; pyramid_tm will commit the transaction when the view is automatically returned (provided that exceptions are not raised). This will be the correct way to start the view and will throw the correct exception even from within IPython:

 def pretend_view(request): """Pretend view in a Pyramid application using pyramid_tm""" session = DBSession() # You're using a sessionmaker, so you should make a session! user = User() session.add(user) session.flush() return user 

if you really want to make a transaction from a view:

 def pretend_view(request): """Pretend view in a Pyramid application using pyramid_tm""" session = DBSession() user = User() session.add(user) session.flush() import transaction transaction.commit() return user 

Other resources

SQLAlchemy-Pyramid cookbook: http://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki2/index.html#bfg-sql-wiki-tutorial

pyramid_tm documentation: http://pyramid-tm.readthedocs.org/en/latest/

+2
source share

All Articles