我正在尝试将带有python3.6的csv (它有一个头和引号字符)复制到远程postgres 10服务器上的一个表中。它是一个大型CSV (2.5M行,800 It ),虽然我以前将它导入数据文件,然后使用dataframe.to_sql,但这非常占用内存,所以我转而使用COPY。
将复制与psycopg2或sqlalchemy一起使用会很好,但远程服务器无法访问本地文件系统。
在终端中使用psql,我已经成功地运行了下面的查询来填充表。我认为在psycopg2或sqlalchemy中使用\copy是不可能的。
\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '"' NULL ''但是,当我尝试像下面这样使用一行psql -c命令时,它不起作用,我得到了错误:
错误:复制引号必须是一个单字节字符.
psql -U user -h ip -d db -w pw -c "\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '"' NULL ''"你能告诉我为什么会这样吗?
这条单行-c psql语句在python中使用子进程模块实现要比打开终端和执行命令要容易得多,我不知道该如何做。如果你能提出一个解决办法或不同的方法,那就太好了。
======根据安德鲁的建议,将引号字符转义到命令行中。但是,在像下面这样在python中实现它时,会出现一个新的错误:
/bin/sh:-c:第0行:寻找匹配的‘’时意外的EOF
/bin/sh:-c:第1行:语法错误:文件意外结束
"\"\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '\"' NULL ''\""
cmd = f'psql -U {user} -h {ip} -d {db} -w {pw} -c {copy_statement}'
subprocess.call(cmd, shell=True)发布于 2017-10-16 15:19:53
如果你能避免的话,尽量不要使用shell=True。最好自己标记命令以帮助sh。
subprocess.call(["psql", "-U", "{user}", "-h", "{ip}", "-d", "{db}", "-w", "{pw}", "-c", "{copy statement}"])在本例中,复制语句可以逐字传递给psql,因为没有shell引用问题需要考虑。(对于python,请注意,仍然需要引用这段代码,因此字符串将保持原样)。
如果仍然希望使用shell=True,则必须转义python和shell的字符串文本。
"\"\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '\\\"' NULL ''\""将在python中创建一个字符串,
"\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '\"' NULL ''\"这就是我们发现我们首先需要在我们的外壳上!
编辑(从评论中澄清某些内容)
subprocess.call,当不使用shell=True时,需要一个可迭代的参数。
所以你可以
psql_command = "\"\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '\\\"' NULL ''\""
# user, hostname, password, dbname all defined elsewhere above.
command = ["psql",
"-U", user,
"-h", hostname,
"-d", dbname,
"-w", password,
"-c", psql_command,
]
subprocess.call(command)见https://docs.python.org/2/library/subprocess.html#subprocess.call或https://docs.python.org/3/library/subprocess.html#subprocess.call
额外编辑:-请注意,为了避免shell注入,您应该使用这里描述的方法。请参阅https://docs.python.org/2/library/subprocess.html#frequently-used-arguments的警告部分
https://stackoverflow.com/questions/46758865
复制相似问题