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"
这里的解决方案几乎没有限制
- 我不能使用dataframe的to_sql方法,我在这里做批量复制,to_sql太慢了..
- 因为第一个,我必须按照我上面列出的程序,to_csv,然后将csv复制到DB,这意味着我不能使用任何代码来格式化“1.5637e+ 07",除了在 to_csv 方法中设置 float_format..
- 关于 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 整数可以处理无限值,最多内存有限)
首先,让我展示如何重现该问题。设置简单。
这是我的简单测试 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
中创建一个测试 tablecreate 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"
这里的解决方案几乎没有限制
- 我不能使用dataframe的to_sql方法,我在这里做批量复制,to_sql太慢了..
- 因为第一个,我必须按照我上面列出的程序,to_csv,然后将csv复制到DB,这意味着我不能使用任何代码来格式化“1.5637e+ 07",除了在 to_csv 方法中设置 float_format..
- 关于 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 整数可以处理无限值,最多内存有限)