Jump to content

Archived

This topic is now archived and is closed to further replies.

fred silva

Problemas ao inserir com SQLAlchemy

Recommended Posts

Boa tarde,
estou trabalhando numa aplicação aqui no serviço, onde eu preciso ler arquivos em um diretório e gravar o conteúdo das linhas no banco de dados.
O arquivo contém linhas mais ou menos da forma abaixo:

 

AAAAA|120|20121108|20121108
00000|00089109420510001|01071231301548920|00042081739161509023|20121108112203
01000|01071231301549640|258,77|0,00|0,00|258,77|20121120|20121120|258,77
01500|201101|2749,30
01501|201101|2749,30
01502|201101|0,00
01500|201102|4176,15
01501|201102|4176,15
01502|201102|0,00
......continua

 



Como vcs podem ver a linha que inicia com 01500 se repete, e é justamente nela que dá o problema. As linhas 00000 e 01000 grava normal, pois elas não se repetem, mas a linha 01500 só insere a primeira, na próxima dá o erro:
state.session_id, self.hash_key))
sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '3' (this is '4')


Eu acredito que tá dando este problema porque estou tentando gravar o mesmo objeto novamente, mas não estou sabendo como proceder. Alguém pode me dar um força?
Segue o código:

 

def importFile(self, url):
    fileImport = open(url, 'r')
    lines = fileImport.readlines()
    fileImport.close()
    pgdasd = Pgdasd()
    banco = Banco()
    i = 0
    while i < len(lines):
        line = lines[i].replace("\n","").replace(",",".").split("|") # ler a linha do   arquivo, retira os \n e troca , por .
        if line[0] == '00000':
            pgdasd = pgdasd.setPgdasd_00000(line)#Coloca os valores da linha no objeto
            banco.insere(pgdasd)
        if line[0] == '01000':
            pgdasd.Pgdasd_01000 = pgdasd.Pgdasd_01000.setPgdasd_01000(line) #Coloca os valores da linha no objeto
            banco.insere(pgdasd.Pgdasd_01000)
        if line[0] == '01500':
            pgdasd.Pgdasd_01500 = pgdasd.Pgdasd_01500.setPgdasd_01500(line) #Coloca os valores da linha no objeto
            banco.insereLista(lista_01500)

        i = i + 1

class Banco():

    def insere(self, pgdasd):
        engine = create_engine('oracle://ssss:ddddd@xxxx')
        Session = sessionmaker(bind=engine)
        session = Session()
        session.add(pgdasd)
        session.commit()

 

Agradeço a ajuda!

T+

Share this post


Link to post
Share on other sites

http://stackoverflow.com/questions/12782846/sqlalchemy-if-not-query-session-already-attached

http://stackoverflow.com/questions/5544774/whats-the-recommended-scoped-session-usage-pattern-in-a-multithreaded-sqlalchem

http://stackoverflow.com/questions/12037818/handling-several-instances-and-states-of-the-same-entity

http://www.mail-archive.com/sqlalchemy-users@lists.sourceforge.net/msg02009.html

 

Uso o SQLAlchemy com o Oracle, mas como no meu caso não uso sessões, o máximo que posso fazer p/ te ajudar é indicar sites. O melhor seria ler a documentação do SQLAlchemy:

 

http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html

http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#committing

 

Normally, instances loaded into the Session are never changed by subsequent queries

 

A grosso modo, me parece que vc só está criando sessões que permanecem abertas (na mensagem vc vê 2 sessões sendo mencionadas e o engine parece ser um global -- único) e está adicionando a mesma referência (vulgo endereço de memória) que conteria o objeto na sessão.

Share this post


Link to post
Share on other sites

Parece que vc tem razão. Não estou fechando as sessões. Vou ver isso.

Vc disse que não usa sessão? De que forma vc trabalha as inserções?

Share this post


Link to post
Share on other sites

É que na verdade eu não to inserindo nada no banco. O que eu fiz foi criar uma engine e executar uns SQL de leitura medonhos do Oracle p/ pegar os metadados das colunas p/ gerar os arquivos de classe na linguagem que eu preciso.

 

Tente criar somente uma sessão, mesmo que seja global. Se ainda assim não funcionar, tente usar o deepcopy (http://docs.python.org/2/library/copy.html) no objeto antes de associar ele à sessão.

Share this post


Link to post
Share on other sites

_Isis_, consegui resolver!

O problema era porque eu esta criando as classes encadeadas tipo:

 

class Pgdasd(Base):
    
    __tablename__ = 'pgdasd'
    
    PGDASD_00000_ID_DECLARACAO    = Column(String, primary_key = True)
    PGDASD_00000_NUM_RECIBO       = Column(String)
    #Demais campos
        
    def __init__(self):
        self.Pgdasd_01000 = Pgdasd_01000()

Então no momento em que eu ia atribuir o valores ao Pgdasd_01000, por exemplo, eu não instanciava ele eu apenas chamava ele por meio da classe Pgdasd que já estava instanciada. Assim:

 

pgdasd.Pgdasd_01000 = pgdasd.Pgdasd_01000.setPgdasd_01000(line)

obs: line é a linha do arquivo lido.

Desta forma o objeto que estava sendo inserido era sempre uma instância da classe Pgdasd. E como o Pgdasd_01000 se repete, ele só inseria a primeira vez. A partir daí dava aquele erro porque este objeto já tinha sido inserido naquela sessão.

Resolvi instanciando a classe Pgdasd_01000 e atribuindo os valores a ela para cada linha que constasse no arquivo.

Vlw pela força!

Abraços!

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.