是否可以通过psycopg2运行以下命令?如果是这样,我该怎么做?
COPY table_name(col1,col2) FROM 'path/to/file.csv' WITH HEADER DELIMITER ',' CSV;
答案 0 :(得分:14)
是!
http://initd.org/psycopg/docs/cursor.html#cursor.copy_from
import psycopg2
dbname=...
user=...
password=...
host=...
port=...
con = psycopg2.connect(database=dbname,user=user,password=password,host=host,port=port)
cur = con.cursor()
f = open('path/to/file.csv')
cur.copy_from(f, 'test', columns=('col1', 'col2'), sep=",")
con.commit()
con.close()
答案 1 :(得分:4)
Google psycopg2 copy
搜索the psycopg manual,其中包含有关使用客户端COPY
的说明。
如果你想要服务器端COPY
,你就像任何其他SQL一样运行语句。
如上所述,命令没有任何意义。我认为你打算写一个COPY ... TO
或COPY ... FROM
命令,并在隐藏真实文件名等的情况下对其进行修改。
答案 2 :(得分:0)
copy_from
命令对于基本用例很有用:
with open('path/to/file.csv') as f:
cursor.copy_from(f, 'table_name', columns=('col1', 'col2'), sep=',')
请注意,按照您的问题中的描述复制 CSV 数据时,各种问题将阻止您使用 copy_from - 标题行、引用值、包含逗号的值。可以使用 copy_expert
命令通过简单的手动编写的 COPY 查询导入 CSV:
with open('path/to/file.csv') as f:
cursor.copy_expert('COPY table_name(col1, col2) FROM STDIN WITH HEADER CSV', f)
答案 3 :(得分:-2)
有一个使用copy_from
的交易破坏者:它不识别引用的字段,例如如果您有一个值with, a comma
并使用csv.writer,则该值将写为,"with, a comma"
。 psycopg2无法识别此错误(请参阅@shrinathM的引号字符串注释)。
这就是为什么在大多数情况下,您需要退回到更基本的copy_expert
。
也就是说,在使用COPY
时,我发现的另一个困难是要理解CSV的结构,以便postgres正确使用它。这里是使用StringIO
而不是文件的基本代码。
data
是列表列表。并且内部列表的项目对应于columns
import io
import csv
import datetime
f = io.StringIO()
w = csv.writer(f)
data = [
['Hans', [1,2,3], True],
['Kurt', [4], False],
]
columns = ['name', 'ids', 'has_foo']
print('convert to csv format')
for l_in in data:
l_out = []
for v in l_in:
if v == None:
l_out.append('')
elif type(v) in [str, int, datetime.date]:
l_out.append(str(v))
elif type(v) in [list, set, tuple]:
l_out.append('{' + ','.join(str(i) for i in v) + '}')
elif type(v) == bool:
if v:
l_out.append('t')
else:
l_out.append('f')
else:
print(f'unsupported type {type(v)}, writing str()')
l_out.append(str(v))
w.writerow(l_out)
print('actual copy')
f.seek(0)
cursor = conn.cursor()
cursor.copy_expert(f"""COPY my_table ({','.join(columns)}) FROM STDIN WITH (FORMAT CSV)""", f)
conn.commit()