使用命令行,我确认以下命令正确执行
echo '\c mydatabase;\i db-reset.sql' | psql -U postgres -h localhost
但是,在Python中,我可以确认以下行绝对没有任何内容,并返回状态代码0。
import subprocess
code = subprocess.call(r"echo '\c mydatabase;\i db-reset.sql' | psql -U postgres -h localhost", shell=True)
assert code == 0 # This comes to true
基本上,为什么使用子进程调用的命令实际上没有做任何事情?
答案 0 :(得分:5)
它可以工作,但你需要更多的反斜杠。
另外,我建议你不要在这里使用shell=True
。
这就是你做的,但没有shell:
p = subprocess.Popen(['psql', '-U', 'postgres', '-h', 'localhost'], shell=False, stdin=subprocess.PIPE)
p.communicate(r"\c mydatabase;\i db-reset.sql")
答案 1 :(得分:2)
psql
来与Python的进行PostgreSQL通信。
使用the psycopg2
module,它几乎无处不在,可以直接与PostgreSQL对话。这将极大地简化您的数据库通信。
对于实际需要psql
的情况,如运行脚本,请使用psql -f
和数据库参数。在这种情况下,您的命令应该是:
try:
subprocess.check_call([
'psql', '-q',
'-U', 'postgres',
'-h', 'localhost',
'-f', 'db-reset.sql',
'mydatabase'
])
except subprocess.CalledProcessError, ex:
print("Failed to invoke psql: {0}".format(ex))
...甚至更好,如果您使用的是足够新的Python版本,请使用check_output
,这样您也可以捕获错误输出。请注意-q
(安静模式)标志。
(请注意,当你在像Windows这样没有合理subprocess
变体系统调用或等价物的平台上运行时,execv
会自行转义。所以你不需要关心痛苦的外壳逃避怪癖。)