在while循环中复制到Postgres

时间:2019-01-23 06:02:13

标签: python postgresql psycopg2

python有一个奇怪的问题,不是不确定这是否与psycopg2有关,还是与python有关的菜鸟错误。

基本上,我有一个功能,可以从csv复制数据并尝试使用psycopg2将其插入pgsql数据库。如果存在数据类型错误,我希望代码尝试对其进行更正,然后重新尝试将数据插入数据库中。这是代码:

def copy(self, csvFile):
    error = True
    i = 0
    while error:
        try:
            i += 1
            print(f'attempt {i}')
            self.connect()
            csr = self.conn.cursor()
            csr.copy_expert("COPY foo.bar FROM STDOUT NULL '' CSV HEADER", csvFile)
        except psycopg2.DataError as err:
            print(err)
            print(err.pgcode)
            csr.close()
            self.conn.close()
            #self.conn.rollback()
            if err.pgcode == '22001':
                if 'character varying' in err.args[0]:
                    currlength = re.search(r'\((.*?)\)', err.args[0]).group(1)
                    newlength = int(currlength) * 2
                    s = err.args[0].split()
                    col = s[s.index('column') + 1].replace(':','')
                    sql = f'alter table foo.bar alter column {col} type varchar({newlength})'
                    print(f'Column Length too short adjusting {col} from {currlength} to {newlength}\n {sql}')
                    self.execute(sql)
            elif err.pgcode == '22p02':
                s = err.args[0].split()
                col = s[s.index('column') + 1].replace(':', '')
                sql = f'alter table foo.bar alter column {col} varchar(64)'
                print(f'numeric column {col} contains text altering to varchar')
                self.execute(sql)
        else:
            self.conn.commit()
            csr.close()
            error = False

发生的情况是,第一次尝试按预期执行并抛出错误,然后alter table语句正确运行,第二次尝试copy_expert函数不执行任何操作但没有错误,并且在不将csv数据插入数据库的情况下完成了代码。这是显示它第二次尝试的输出。

> attempt 1 
> value too long for type character varying(1) CONTEXT:  COPY
table, line 3, column id: "12345678"
> 
> 22001 
> Column Length too short adjusting assetid from 1 to 2  
> alter table foo.bar alter column id type varchar(2) 
> Executing query alter table foo.bar alter column assetid type varchar(2)             
> attempt 2
> Download and insert of file.csv Complete

1 个答案:

答案 0 :(得分:1)

因此,在花了大约30分钟的热情走下一条盲巷之后,我认为我找到了问题的根源。它与psycopg2无关,我也不必称其为菜鸟错误。实际上,我非常确信这与隔离级别有关……不是。

这是文件句柄。 copy_expert完全读取了文件,因此当psycopg2.DataError上升时,内部指针位于其末尾。第二次没有任何可读取的内容。

如果将csvFile.seek(0)放在except块中,则指针将重置为文件的开头。

except psycopg2.DataError as err:
    csvFile.seek(0)

我已经使用您的copy方法创建了一个小的测试类,并以我认为的方法实现了方法executeconnect
我能够重现您在帖子中描述的行为,并重置except块中的指针,导致第二次尝试修改后,文件中的数据在数据库中可见列长。