我想在我的Python代码中使用“ raster2pgsql”实用程序。当我在Linux终端中使用它时,它可以正常工作。这是命令:
$ raster2pgsql -a "/mnt/c/Users/Jan/path/to/raster/dem.tiff" test_schema.raster2 | psql -h localhost -d pisl -U pisl
然后,我使用subprocess.run(我也尝试过subprocess.call)在我的Python代码中使用相同的工具。这是我的代码:
from subprocess import run
command = ["raster2pgsql", "-a", '"' + file_name + '"', self.schema_name + "." + identifier, "|", "psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command)
我收到此错误:
ERROR: Unable to read raster file: "/mnt/c/Users/Jan/path/to/raster/dem.tiff"
打印command
给出了我认为正确的信息(相当于终端中的工作方式):
['raster2pgsql', '-a', '"/mnt/c/Users/Jan/path/to/raster/dem.tiff"', 'test_schema.raster2', '|', 'psql', '-h', 'localhost', '-p', '5432', '-d', 'pisl']
我已经仔细检查了栅格文件的路径是否正确,尝试使用单引号,双引号,但没有任何帮助。我看过许多类似的问题(here,here或here),但没有发现任何帮助。
我在Windows 10中使用Python 3.5和Linux Bash Shell。
问题:我使用子流程的方式有什么问题?
答案 0 :(得分:3)
2个问题:
"/tmp/something"
的文件,所以命令失败。shell=True
如此快捷的解决方法:
command = ["raster2pgsql", "-a", file_name, self.schema_name + "." + identifier, "|", "psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command,shell=True)
或使用命令字符串(因为shell=True
对参数列表很挑剔)
command = "raster2pgsql -a "+ file_name + " " + self.schema_name + "." + identifier + " | psql -h localhost -p 5432 -d" + self.dbname
run(command,shell=True)
(丑陋,不是吗?)
最好在没有shell=True
的情况下运行2个进程,并使用python将它们通过管道连接在一起,从而更加可移植和安全(不确定shell=True
在Linux上如何与参数列表交互) ):
from subprocess import *
command1 = ["raster2pgsql", "-a", file_name, self.schema_name + "." + identifier]
p = Popen(command1,stdout=PIPE)
command2 = ["psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command2,stdin=p.stdout)
创建的第一个Popen
对象将其输出写入管道(由于stdout=PIPE
参数)。 run
函数也可以将输入作为管道(由于stdin=p.stout)
。它消耗了第一个命令的输出,从而创建了本机管道命令链,而无需使用shell(以及引号,空格,特殊字符解释等注意事项...)