2013-08-20 1 views
7

현재 사용중인 모델에서 null 일 수없는 "name"필드가 있습니다.SQLAlchemy의 트랜잭션 오류가 적절한 추적을 반환하지 않습니다. (Python 2.7)

사용자 개체를 만들고이를 Pyramid에서 제공하는 DBSession에 추가하고 트랜잭션과 함께 제출하는 방법을 시도합니다. 나는 검증 문제가 있습니까, 내 위의 트랜잭션에 지금

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

- 나는 사용자에 이름을 지정해야하지만 : 피라미드를 사용하지 않는 사람들을 위해

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

, DBSession입니다 나는하지 않았다. 그러나 대신 말해 오류를 얻는 "당신은 사용자 이름을 지정해야합니다!"나는이 얻을 : 나는 손에서 문제를 발견했습니다

<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 

어딘가에, 파이썬 버전이있다,이다 vs 3 비 호환성 (여기서는 TypeError: 'str' does not support the buffer interface). 나는 SQLAlchemy가 파이썬 3+ 이상을 지원한다는 것을 알고있다. 그래서 문제가 어디에서오고 있는지 알 수있다.

트랜잭션을 올바르게 수행하면 오류가 발생하지 않습니다.

traceback.py에서 코드를 덮어 쓰지 않고도이 문제를 해결할 수있는 방법이 있습니까?

+0

오류를 재현하는 데 필요한 코드를 제공하겠습니까? – javex

+0

나는 당신이 무엇을 볼 필요가 있는지 잘 모르겠습니다. User 모델에는 SQLAlchemy 컬럼이 몇 개 있고, 에러를 제대로 처리 할 수 ​​없다는 것과 관련이 없다. (이 문제는 모든 모델에서 발생했는데, 특정 컬럼에 대해 유효하지 않은 엔트리로 커밋하려고 할 때만 발생했다) – limasxgoesto0

+2

새 virtualenv에서 오류를 재현 할 수있는 최소한의 코드와 요구 사항 파일을 제공 할 수 있습니까? –

답변

2

오류는 (적어도 직접적으로) SQLAlchemy에 의해 야기 된 것이 아니라 SQLAlchemy, IPython 및 사용자가 transaction을 사용하는 방법의 조합으로 인해 발생합니다. 이러한 도구의 권장 사용법을 따르면 빠져 나갈 것입니다.

면책 조항 : 아래는 피라미드에서 범위가 지정된 세션과 ZopeTransactionExtension을 사용하는 권장 방법이 아니지만 가능한 한 제공 한 코드와 밀접하게 연관되어 있습니다.

파일에 이것을 넣고 SQLAlchemy의 설치와 VIRTUALENV에서 실행하면 SQLAlchemy의에서 올바른 오류 메시지가 표시됩니다 : 당신이 불 경우 sqlalchemy.exc.IntegrityError: (IntegrityError) NOT NULL constraint failed: user.name u'INSERT INTO user DEFAULT VALUES'()

:

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") 

이 예외를 생성합니다 IPython 대신 pretend_view를 실행하면 언급 한 유니 코드 오류가 발생합니다. 당신이 IPython에서 올바른 오류 메시지가 표시하려면 지금 pyramid_tm

적절한 사용은, "제대로"세션을 사용!

일반적으로 코드에 transaction을 명시 적으로 사용할 이유가 없습니다. pyramid_tm은 뷰가 자동으로 반환 될 때 트랜잭션을 커밋합니다 (예외가 발생하지 않는다고 가정).이보기를 실행할 수있는 적절한 방법이 될 것입니다, 심지어 IPython 내에서 올바른 예외를 생성합니다

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 

: 당신이 정말보기 내에서 트랜잭션을 커밋하려면

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 

을 기타 리소스

SQLAlchemy의-피라미드의 요리 책 : http://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki2/index.html#bfg-sql-wiki-tutorial

pyramid_tm d를 설명 : http://pyramid-tm.readthedocs.org/en/latest/

+0

오, 나는이 질문을 쓴 이후로 오래되었습니다. 우리는 코드에서 트랜잭션을 사용하지 않습니다 (또는 ZTE의 작동 방식을 파악하기 전에 하루 또는 이틀 동안). 그러나 pshell/ipython에서 데이터를 조작해야 할 때이 트랜잭션을 사용합니다. 우리는 확실히 우리의 관점에서 거래를 사용하지 않습니다. ipython에서 트랜잭션을 사용해야 할 때 transaction.manager보다 일반적으로 transaction.commit()을 사용합니다. 오류 메시지는 이후로 문제가되지 않습니다. – limasxgoesto0