psycopg2:copy_expert 包含 e+ 整数的 csv 文件

psycopg2: copy_expert csv file containing e+ integer number

首先,让我展示如何重现该问题。设置简单。

这是我的简单测试 csv 文件

a;b
1;1
0;2
1.5637e+07;3

测试csv文件由pandas数据帧的to_csv方法生成

import csv, pandas as pd

d = {'a' : pd.Series([1, 0.0, 1.5637e+07]),'b' : pd.Series([1, 2, 3])}

df = pd.DataFrame(d)

df_csv = df.to_csv('test.csv', encoding="utf-8", index=False,
                   sep=';', quotechar='"', float_format="%g", quoting=csv.QUOTE_MINIMAL)    

然后,让我们在 db

中创建一个测试 table
create table testtb (
    a integer,
    b integer
)

最后,我尝试将 csv 文件导出到 table,这里设置了一些代码

def parse_column(header):
    column_str = ",".join(header[0].split(";"))
    return column_str

conn = psycopg2.connect("dbname=test1 " +
                            " user=postgres" +
                            " host=localhost" +
                            " password=password")

cur = conn.cursor()

with open('test.csv', "r") as f:
    reader = csv.reader(f)
    header = next(reader)
    f.seek(0)

    copy_sql = """
            COPY {}.{}({}) FROM STDIN CSV HEADER DELIMITER ';'
            """.format("public", "simplew", parse_column(header))
    cur.copy_expert(sql=copy_sql, file=f)

conn.commit()

问题是,现在我得到

invalid input syntax for integer: "1.5637e+07"

这里的解决方案几乎没有限制

  1. 我不能使用dataframe的to_sql方法,我在这里做批量复制,to_sql太慢了..
  2. 因为第一个,我必须按照我上面列出的程序,to_csv,然后将csv复制到DB,这意味着我不能使用任何代码来格式化“1.5637e+ 07",除了在 to_csv 方法中设置 float_format..
  3. 关于 float_format,我需要去除浮点数的尾随零,所以我目前将其设置为 %g

最后,我通过这种方式获得了输入数据帧:

df = DataFrame.from_records(list(  my_api_call()   ))

我上面编的例子只是为了说明情况

1.5637e+07 不是整数。这是一个浮点数

>>> 1.5637e+07
15637000.0
>>> type(1.5637e+07)
<class 'float'>

如果您想要一个整数,只需执行 15637*10**3 或简单地 15637000。那将是一个整数。

pd.Series([1, 0.0, 15637000])

注意:int(1.5637e+07) 也可以在这里工作,但会因最高 10 次方的精度损失而失败:(int(1.5637e+22) = 15637000000000000786432) 所以最好坚持整数求幂,与 C 整数不同,python 整数可以处理无限值,最多内存有限)