2 Questão: Como acessar o erro psycopg2 envolto em erro sqlalchemy

pergunta criada em Wed, May 8, 2019 12:00 AM

Estou fazendo o upload de um quadro de dados de pandas para uma tabela no Postgres usando SQLalchemy e psycopg2. Como faço para acessar o erro psycopg2 que está dentro do erro SQLalchemy?

Eu quero escrever uma exceção no meu código apenas quando ele gerar um erro devido a um valor nulo em uma coluna que viola a restrição não-nula. Eu sei como testar esse erro pSQL exato com psycopg2, mas quando executo meu código, ele retorna um erro SQLalchemy.

Aqui está o erro:

  

SQLalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) valor nulo na coluna ...

Aqui está a exceção necessária:

from sqlalchemy import exc

try:
    df.to_sql(name='sql_table', con=engine, if_exists='append', index=False)
except exc.IntegrityError:

Aqui está o que eu quero fazer:

from sqlalchemy import exc
import psycopg2

try:
    df.to_sql(name='sql_table', con=engine, if_exists='append', index=False)
except exc.IntegrityError as ex:
    ex = ex.psycopg2error
    if ex.pgcode == '23502'
        print('Data not uploaded: null value in a column violates non-null constraint')
    else:
        raise

Eu sei que posso testar sqlalchemy.exc.IntegrityEror.orig, mas isso não é tão limpo ou refinado quanto usando o membro pgcode.

    
0
2 Respostas                              2                         

Como você apontou na sua pergunta, você pode acessar a exceção subjacente gerada pelo dbapi através do atributo .orig da exceção SQLAlchemy.

Qualquer exceção levantada pelo driver e propagada pelo SQLAlchemy é encapsulada por uma subclasse de DBAPIError , onde está o estado docs:

  

O objeto de exceção empacotado está disponível no atributo orig.   tipo e propriedades são específicas da implementação do DB-API .

(ênfase minha)

Olhando os documentos do psycopg para sua base Error os atributos que eles chamam são pgcode:

  

String representando o código de erro retornado pelo backend, None if   não disponível. O módulo errorcodes contém constantes simbólicas   representando códigos de erro do PostgreSQL.

Assim, <sqla_exc>.orig.pgcode parece que deve ter o que você procura, mas se por alguma razão o psycopg não disponibilizar seu código em seu estado de exceção, não é algo que o sqlalchemy possa endereçar pois apenas quebra sua exceção e passa para você.

    
2
2019-05-09 00: 47: 07Z

Aqui está o meu código final para referência:

try:
    df.to_sql(name='sql_table', con=engine, if_exists='append', index=False)
except exc.DBAPIError as ex:
    if ex.orig.pgcode == '23502':
        print("Data could not be uploaded to sql_table: " + ex.orig.diag.message_primary)
    else:
        raise
    
1
2019-05-10 15: 22: 15Z
fonte colocada Aqui