首页 > 解决方案 > 如何从python调用和管道多个postgres命令

问题描述

为了将类似文件的对象复制到postgres数据库,我采取以下步骤:

~$ sudo psql -U postgres
password for root: 
password for user postgres:
postgres=# \c migration v0
You are now connected to database "migration_v0" as user "postgres".
migration_v0=# cat file.csv | \copy table1 from stdin csv

我想采取完全相同的步骤,但从Python内部并希望传递StringIO缓冲区而不是文字文件。我的第一次尝试包括以下步骤:

# test.py

fmt = r"copy table1 FROM stdin csv"
sql = fmt.format(string_io)
psql = ['psql', '-U', 'postgres', '-c', sql]
output = subprocess.check_output(psql)
print(output)

该命令已执行(弹出提示输入用户postgres的密码),但我收到以下错误:

错误:关系“table1”不存在

发生这种情况是因为我目前正在尝试\copy在默认数据库postgres而不是migration_v0. 因此,我想在子进程调用(\c migration_v0\copy ...)中包含这两个命令,但我不知道该怎么做,因为 postgres 的标志-c只需要一个命令。

我查找了一种解决方法,并遇到了这个命令行示例:

\c migration_v0 \\ \copy ... | psql -U postgres

,但我不知道如何将其移植到 python 代码中。

关于如何解决这个问题的任何建议?

编辑 1

我意识到该标志-d还可以切换数据库,所以现在我不需要运行多个命令。我的代码现在看起来像这样:

p = subprocess.Popen([
                         'psql', '-U', 'postgres', 
                         '-d', 'migration_v0', 
                         '-c', '\copy table1 FROM stdin csv'], 
                      shell=False, 
                      stdin=string_io)

但我收到以下错误:

io.UnsupportedOperation: 文件号

显然StringIO没有实现fileno。在这一点上,我想知道是否有可能通过子流程调用来实现我想要的。

标签: python-3.xpostgresqlcommand-linepipe

解决方案


推荐阅读