16

Per quanto mi sforzassi, non posso non sembrano prendere lo sqlalchemy IntegrityError correttamente:non può prendere SQLAlchemy IntegrityError

from sqlalchemy import exc 

try: 
    insert_record() 
except exc.IntegrityError, exc: 
    print exC# this is never called 
    handle_elegantly() # this is never called 

Come quello che ci si potrebbe aspettare:

IntegrityError: (IntegrityError) insert or update on table "my_table" 
       violates foreign key constraint "my_table_some_column_fkey" 

Ho cercato di esplicito :

from sqlalchemy.exc import IntegrityError 

UPDATE:

ho trovato qualcosa che sembra adattarsi cosa sta succedendo qui, dove l'integrità errore non è gettato fino a quando la sessione viene svuotata al db, e dopo sono stati eseguiti i try/except blocchi: Trying to catch integrity error with SQLAlchemy

Tuttavia, l'aggiunta di session.flush() nel blocco try produce un InvalidRequestError:

ERROR:root:This Session's transaction has been rolled back due to a previous 
      exception during flush. To begin a new transaction with this Session, 
      first issue Session.rollback(). 
      Original exception was: (IntegrityError) 
+0

Are sei al 100% dove sta succedendo? –

+0

Quale database stai usando? – alecxe

+0

Inoltre, si modifica l'errore 'IntegrityError' con' DatabaseError'? Grazie. – alecxe

risposta

14

non appena il IntegrityError viene sollevata, a prescindere dal fatto che hai preso l'errore, la sessione si stava lavorando in viene invalidata. Come il secondo messaggio di errore che sta istruendo, To begin a new transaction with this Session, first issue Session.rollback()., di continuare a utilizzare la sessione è necessario emettere un session.rollback()

Non posso dirlo con certezza, ma voi o il vostro framework web sta tentando di continuare a utilizzare la sessione sto indovinando che ha sollevato l'errore Integrity in qualche modo. Vi consiglio di inviare un session.rollback() dopo aver rilevato l'eccezione o nella vostra funzione handle_elegantly.

Se si esegue il seguito vedrete cosa voglio dire:

from sqlalchemy import types 
from sqlalchemy import exc 
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 handle_elegantly(name): 
    session = DBSession() 
    session.add(User(name=name)) 
    session.flush() 
    print 'Exception elegantly handled!!\n' 


def pretend_view(request): 
    """Pretend view in a Pyramid application using pyramid_tm""" 
    session = DBSession() 
    user = User() 
    print '\n-------Here we rollback before continuing -------' 
    try: 
     session.add(user) 
     session.flush() 
    except exc.IntegrityError: 
     session.rollback() 
     handle_elegantly('This will run fine') 

    print '\n------- Here we do not, and this will error -------' 
    try: 
     session.add(user) 
     session.flush() 
    except exc.IntegrityError: 
     handle_elegantly('Exception will be raised') 


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() 
    pretend_view("dummy request") 
9

ho la stessa necessità nella mia applicazione Flask, mi occupo di esso come qui di seguito e funziona:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from sqlalchemy import exc 

db = SQLAlchemy(Flask(__name__)) 

try: 
    db.session.add(resource) 
    return db.session.commit() 
except exc.IntegrityError as e: 
    db.session().rollback() 
+0

Grazie, stavo cercando di usare 'exc.IntegrityError' senza importarlo da sqlalchemy prima –