2013-08-20 6 views
7

私の現在のモデルのUserでは、 "name"フィールドはnullにはできません。SQLAlchemyのトランザクションのエラーが適切なトレースバックを返さない(Python 2.7)

私はユーザオブジェクトを作成し、それをPyramidが提供するDBSessionに追加し、それをトランザクションとして送信してみます。ピラミッドを使用していない人のために

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 

はどこか、Pythonのバージョン2があります、ということですここではTypeError: 'str' does not support the buffer interfaceと表示されています。私はSQLAlchemyがPython 3+をサポートしていることを知っているので、そこから問題が発生している可能性があります。

私のトランザクションを正しく行うと、エラーはスローされません。

traceback.pyのコードを上書きすることなくこの問題を回避する方法はありますか?

+0

エラーを再現するための完全なコードを提供していただけますか? – javex

+0

他に何が必要なのか分かりません。 UserモデルにはいくつかのSQLAlchemyカラムがありますが、エラーを正しく処理できないこととは関係ありません(これは、これを試したすべてのモデルで起こりましたが、特定のカラムに対して無効なエントリをコミットしようとしている場合のみ) – limasxgoesto0

+2

新しいvirtualenvでエラーを再現するための最小限のコードと要件ファイルを提供できますか? –

答えて

2

あなたが見ているエラーは(少なくとも直接的に)SQLAlchemyに起因するものではなく、SQLAlchemy、IPython、および使用しようとしている方法の組み合わせによって引き起こされます。transaction。これらのツールの推奨される使い方に従えば、それはなくなります。

免責事項:以下は、スコープ付きセッションとZopeTransactionExtensionをPyramidsで使用するための推奨方法ではありませんが、提供されたコードに可能な限り近づけたいと思います。

ファイルでこれを入れて、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を実行すると、あなたが言及したUnicodeエラーを受け取ります。 pyramid_tm今

適切な使用、あなたはIPythonで正しいエラーメッセージを表示する場合は、「正しく」セッションを使用!

通常、あなたのコードにtransactionを明示的に使用する理由はありません。 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の-ピラミッドのクックブック:http://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki2/index.html#bfg-sql-wiki-tutorial

pyramid_tmさd ocumentation:http://pyramid-tm.readthedocs.org/en/latest/

+0

ああ、私はこの質問を書いてからずっとずっと続いています。私たちはコードでトランザクションを使用しません(または、そうした場合は、ZTEの仕組みを理解する前に1日か2日間です)が、pshell/ipythonでデータを操作する必要がある場合に使用します。我々は確かに私たちの意見のいずれかでトランザクションを使用していません。 ipythonでトランザクションを使用する必要がある場合は、transaction.managerに対してtransaction.commit()を使用するようになりました。エラーメッセージはそれ以来何の問題も生じていません。 – limasxgoesto0

関連する問題