2016-09-01 26 views
0

私の問題:sqlalchemyがselectでトランザクションを作成しないようにするにはどうすればよいですか?

私はそこにいくつかのデータ行を持つファイルを持っています。私はを試してください私のデータベースにすべての行を挿入するが、のいずれかの行のに問題がある場合、私はキットとkaboodle全体をロールバックする必要があります。しかし、私は実際のエラーを追跡したいので、エラーがある最初のレコードで死んでいるのではなく、次のように言うことができます。

このファイルには42個のエラーがあります。

Line 1 is missing a whirlygig. 
Line 2 is a duplicate. 
Line 5 is right out. 

私はこれをやろうとしている方法は、トランザクションを使用することですが、私はSQLAlchemyのセレクトに暗黙のトランザクションを作成し、問題を抱えている、と明らかに私は本当に何もないので、SQLAlchemyのは、トランザクションを使用する方法を理解していません私は自分が望むやり方で働くようです。ここに私の問題を示し、いくつかのコードは次のとおりです。

import sqlalchemy as sa 
import logging 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 
l = logging.getLogger('sqlalchemy.engine') 
l.setLevel(logging.INFO) 
l.addHandler(logging.StreamHandler()) 

engine = sa.create_engine('YOUR PG CONNECTION HERE') 

Session = sessionmaker(bind=engine) 
session = Session() 
temp_metadata = sa.MetaData(schema='pg_temp') 
TempBase = declarative_base(metadata=temp_metadata) 


class Whatever(TempBase): 
    __tablename__ = 'whatevs' 
    id = sa.Column('id', sa.Integer, primary_key=True, autoincrement=True) 
    fnord = sa.Column('fnord', sa.String, server_default=sa.schema.FetchedValue()) 
    quux = sa.Column('quux', sa.String) 
    value = sa.Column('value', sa.String) 


def insert_some_stuff(session, data): 
    value = session.query(Whatever.value).limit(1).scalar() 
    session.add(Whatever(quux=data, value='hi')) 
    try: 
     session.commit() 
     errors = 0 
    except sa.exc.IntegrityError: 
     session.rollback() 
     errors = 1 
    return errors 


with session.begin_nested(): 
    session.execute(''' 
     CREATE TABLE pg_temp.whatevs (
      id  serial 
      , fnord text not null default 'fnord' 
      , quux text not null 
      , value text not null 
      , CONSTRAINT totally_unique UNIQUE (quux) 
     ); 
     INSERT INTO pg_temp.whatevs (value, quux) VALUES ('something cool', 'fnord'); 
    ''') 
    w = Whatever(value='something cool', quux='herp') 
    session.add(w) 


errors = 0 
for q in ('foo', 'biz', 'bang', 'herp'): 
    with session.begin_nested(): 
     errors += insert_some_stuff(session, q) 
for row in session.query(Whatever).all(): 
    print(row.id, row.fnord, row.value) 

私はsession.begin()または.begin(subtransactions=True)を行うさまざまな組み合わせを試してみたが、彼らは仕事、またはちょうど私がトランザクションをコミットしていますので、本当に奇妙ないないようですすべてのいずれか私は(明示的に)始めたことはありません。

sqlalchemyがselectでトランザクションを作成しないようにすることはできますか?または私はここに何かを逃していますか?私が欲しいものを達成する良い方法はありますか?

+0

SQLAlchemyがこれらのトランザクションを作成するのはなぜ問題でしょうか? – user2357112

+0

最後のトランザクションをクローズするときにトランザクションがクローズするか、*明白な* 'begin'を持たないこの' commit'/'rollback'コールがあるので –

+0

これは役に立ちますか? http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html#joining-a-session-into-an-external-transaction-such-as-for-test-suites – ACV

答えて

1

begin_nestedwithブロックが行く方法です。

あまり使用 begin()方法と同様に

begin_nested()、... - sqlalchemy docs

begin_nestedが好ましい選択肢であると信じて私をリードしています。 withブロックを使用することにより

def insert_some_stuff(session, data): 
    try: 
     with session.begin_nested(): 
      value = session.query(Whatever.value).limit(1).scalar() 
      session.add(Whatever(quux=data, value='hi')) 
     errors = 0 
    except sa.exc.IntegrityError: 
     errors = 1 

    return errors 

それはロールバック/コミット、そして遠くのロールバックではないに来るとき、それは正しいこと™を行います。

関連する問題