我正在尝试使用Popen执行命令。
该命令使用一些PostGIS / Postgresql实用程序将光栅文件上载到数据库,并在从命令行执行时工作。它使用unix样式的管道链接2个命令,如下所示:
"C:\\Program Files\\PostgreSQL\\9.2\\bin\\raster2pgsql.exe" -d -I -C -e -Y -F -t 128x128 "C:\\temp\\SampleDTM\\SampleDTM.tif" test | "C:\\Program Files\\PostgreSQL\\9.2\\bin\\psql.exe" -h localhost -p 5432 -d adr_hazard -U postgres
在Python中使用时,我将其设为包含'
代码的字符串:
command = '"C:\\Program Files\\PostgreSQL\\9.2\\bin\\raster2pgsql.exe" -d -I -C -e -Y -F -t 128x128 "C:\\temp\\SampleDTM\\SampleDTM.tif" test | "C:\\Program Files\\PostgreSQL\\9.2\\bin\\psql.exe" -h localhost -p 5432 -d adr_hazard -U postgres'
尝试执行它会导致错误:
p = subprocess.Popen(command)
ERROR: Unable to read raster file: test
错误似乎没有正确解析命令(它将错误的参数解释为光栅文件)
我使用Popen
错了吗?
答案 0 :(得分:3)
您的command
使用了管道|
。它需要一个shell:
p = subprocess.Popen(command, shell=True)
就我所知,command
本身看起来还不错。
答案 1 :(得分:1)
没有必要使用shell=True
来实现管道。这可以使用管道where concern about insecure input is an issue以编程方式完成。在此处,conn_params
是包含PASSWORD
,NAME
(数据库名称),USER
和HOST
键的字典。
raster2pgsql_ps = subprocess.Popen([
'raster2pgsql', '-d', '-I', '-C', '-e', '-Y', '-F', '-t', '128x128',
'C:\\temp\\SampleDTM\\SampleDTM.tif',
'test'
], stdout=subprocess.PIPE)
# Connection made using conninfo parameters
# http://www.postgresql.org/docs/9.0/static/libpq-connect.html
psql_ps = subprocess.check_output([
'psql',
'password={PASSWORD} dbname={NAME} user={USER} host={HOST}'.format(**conn_params),
], stdin=raster2pgsql_ps.stdout)
答案 2 :(得分:0)
以下内容在Windows上对我有用,同时避免了shell=True
一个人可以利用Python的fstring formatting来确保命令在Windows中可以使用。
请注意,我使用了shp2pgsql
,但这对于raster2pgsql
来说应该是非常相似的过程。
shp2pgsql
的参数:srid
是形状文件的坐标系,filename
是要导入的形状文件的路径,tablename
是名称你想给你的桌子。
import os
import subprocess
shp2pgsql_binary = os.path.join(pgsql_dir, "bin", "shp2pgsql")
psql_binary = os.path.join(pgsql_dir, "bin", "psql")
command0 = f'\"{shp2pgsql_binary}\" -s {srid} \"{filename}\" {tablename}'
command1 = f'\"{psql_binary}\" \"dbname={databasename} user={username} password={password} host={hostname}\"'
try:
shp2pgsql_ps = subprocess.Popen(command0, stdout=subprocess.PIPE)
psql_ps = subprocess.check_output(command1, stdin=shp2pgsql_ps.stdout)
except:
sys.stderr.write("An error occurred while importing data into the database, you might want to \
check the SQL command below:")
sys.stderr.write(command)
raise
要适应raster2pgsql
,只需修改command0
中的字符串,例如-s {srid}
成为-d -I -C -e -Y -F -t 128x128
。 command1
的字符串可以保持不变。
答案 3 :(得分:-1)
PIPE = subprocess.PIPE
pd = subprocess.Popen(['"C:\\Program Files\\PostgreSQL\\9.2\\bin\\raster2pgsql.exe", '-d', '-I', '-C', '-e', '-Y', '-F', '-t', '128x128', "C:\\temp\\SampleDTM\\SampleDTM.tif", 'test'],
stdout=PIPE, stderr=PIPE)
stdout, stderr = pd.communicate()
答案 4 :(得分:-2)
以这种方式使用subprocess.Popen会更好:
proc = subprocess.Popen(['"C:\\Program Files\\PostgreSQL\\9.2\\bin\\raster2pgsql.exe"', '-d', '-I', '-C', '-e', '-Y', '-F', '-t', '128x128', '"C:\\temp\\SampleDTM\\SampleDTM.tif"', 'test', '|', '"C:\\Program Files\\PostgreSQL\\9.2\\bin\\psql.exe"', '-h', 'localhost', '-p', '5432', '-d', 'adr_hazard', '-U', 'postgres'], shell = True, stdout = subprocess.pipe, stderr = subprocess.STDOUT)
proc.wait()
result = proc.stdout.readlines()#if you want to process the result of your command
proc.kill()
B.T.W,首先格式化路径是好的,使用:
path = os.path.normalpath("C:\\Program Files\\PostgreSQL\\9.2\\bin\\raster2pgsql.exe")
这将避免不同OS平台的一些路径问题。
如果您想执行命令就像在本地shell中执行命令一样,shell = True
很重要。