我想在我的 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"
打印命令
给出了我认为是正确的(相当于终端中的工作):
['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。
问题:我使用子流程的方式有什么问题?
最佳答案
这里有 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 上与参数列表 react ):
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)
。它使用第一个命令的输出,创建一个 native 管道命令链,而不需要 shell(以及引用、空格、特殊字符解释等的注意事项......)
关于python - 子进程运行/调用不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51069486/