Python 2.7 SQLAlchemy中的错误';s事务不返回正确的回溯(Python 2.7)
在我当前的模型用户中,我有一个字段“name”,它不能为null 我尝试创建一个用户对象,并将其添加到Pyramid提供的DBSession中,然后将其与事务一起提交,如下所示Python 2.7 SQLAlchemy中的错误';s事务不返回正确的回溯(Python 2.7),python-2.7,sqlalchemy,traceback,Python 2.7,Sqlalchemy,Traceback,在我当前的模型用户中,我有一个字段“name”,它不能为null 我尝试创建一个用户对象,并将其添加到Pyramid提供的DBSession中,然后将其与事务一起提交,如下所示 with transaction.manager: u = models.User() models.DBSession.add(u) 对于不使用金字塔的用户,DBSession是: DBSession = scoped_session(sessionmaker(extension=ZopeTransa
with transaction.manager:
u = models.User()
models.DBSession.add(u)
对于不使用金字塔的用户,DBSession是:
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
现在,在我上面的事务中,我确实有一个验证问题——我需要为用户分配一个名称,但我没有。但是,我得到的不是一个错误,告诉我“您需要为您的用户分配一个名称!”,而是:
<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
()
2 u=型号。用户()
---->3.DBSession.add模型(u)
4.
/home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction//u manager.pyc in\uuuuu exit\uuuu(self、t、v、tb)
118 def出口(自身、t、v、tb):
119如果v为无:
-->120 self.commit()
121.其他:
122自我中止()
/home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction//u manager.pyc in commit(self)
109“请参阅ITransactionManager。
110 """
-->111返回self.get().commit()
112
113 def中止(自身):
/home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction//u transaction.py in commit(self)
276 tb=无
277尝试:
-->278 t,v,tb=自我.\u saveandgetcommissionherror()
279 self.\u callAfterCommitHooks(状态=False)
280重调(t、v、tb)
/home/user/Projects/env/local/lib/python2.7/site-packages/transaction-1.4.1-py2.7.egg/transaction//u transaction.py in\u saveandgetcommitiserror(self)
300进口pdb
301 pdb.set_trace()
-->302回溯打印堆栈(系统获取帧(1),无,英尺)
303#将堆栈条目从这里向下附加到异常。
304回溯。打印\u tb(tb,无,英尺)
/打印堆栈中的usr/lib/python2.7/traceback.py(f,limit,file)
267除零误差外:
268 f=sys.exc_info()[2].tb_frame.f_back
-->269打印列表(提取堆栈(f,限制),文件)
270
271 def格式_堆栈(f=None,limit=None):
/打印列表中的usr/lib/python2.7/traceback.py(提取列表,文件)
23'文件“%s”,第%d行,位于%s%%(文件名,行号,名称))
24如果行:
--->25_打印(文件“%s”%line.strip())
26
27 def格式列表(提取列表):
/打印中的usr/lib/python2.7/traceback.py(文件、str、终止符)
11
12 def_打印(文件,str='',terminator='\n'):
--->13文件写入(str+终止符)
14
15
TypeError:“unicode”没有缓冲区接口
我发现眼前的问题是,在某个地方,存在python版本2与3的不兼容性,如图所示。我知道SQLAlchemy支持Python3+,所以这就是问题的根源
请注意,如果我正确执行事务,则不会抛出任何错误
有没有办法绕过这个问题而不必重写traceback.py中的代码?您看到的错误不是(至少是直接)由SQLAlchemy造成的,而是由SQLAlchemy、IPython和您尝试使用
事务的方式组合而成的。如果您遵循这些工具的推荐用法,它将消失
免责声明:下面不是在金字塔中使用作用域会话和ZopeTransactionExtension的推荐方式,但我希望尽可能地遵守您提供的代码
将其放入一个文件中,并在安装了SQLAlchemy的virtualenv中运行,您将看到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)非空约束失败:user.name u'INSERT INTO user DEFAULT VALUES'()
如果您启动IPython并运行假装_视图,您将收到您提到的unicode错误
正确使用pyramid_tm
现在,如果您想在IPython中看到正确的错误消息,请使用“正确”会话
通常没有理由在代码中明确使用事务
;当视图自动返回时(假设没有引发异常),pyramid_tm将提交事务。这将是运行视图的正确方式,并将生成正确的异常,即使在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
如果确实要从视图中提交事务:
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
其他资源
SQLAlchemy金字塔食谱:
pyramid_tm文档:您能提供完整的代码来重现错误吗?我不确定您还需要看到什么。用户模型只是有几个SQLAlchemy列,它看起来与无法正确处理错误无关(这发生在我尝试过的所有模型上,但仅当尝试提交()时,某些列的条目无效)你能提供一个最小的代码和一个需求文件来在一个新的virtualenv中重现错误吗?哇,我已经很久没有写这个问题了。我们在代码中不使用事务(或者,如果我们使用了事务,在了解中兴通讯的工作原理之前,最多需要一两天),但当数据需要在pshell/ipython中进行操作时,我们会使用事务。我们当然没有在任何视图中使用事务。当我们确实需要在ipython中使用transaction时,我们现在通常在transaction.manager上使用transaction.commit(),并且从那时起错误消息就没有出现任何问题。