如何使用子进程Popen?

问题描述 投票:3回答:5

我正在尝试使用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错误吗?

python postgresql subprocess popen raster
5个回答
3
投票

您的command使用管道|。它需要一个外壳:

p = subprocess.Popen(command, shell=True)

据我所知[command本身看起来还不错。


1
投票

无需使用shell=True即可通过管道实现此目的。甚至可以通过管道where concern about insecure input is an issue以编程方式完成此操作。在这里,conn_params是具有PASSWORDNAME(数据库名称),USERHOST键的字典。

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)

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 128x128command1的字符串可以保持不变。


-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()

-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平台上出现一些路径问题。

[C0很重要,如果您想像在本地shell中执行命令一样执行命令。

希望会帮助您。

© www.soinside.com 2019 - 2024. All rights reserved.