如何从Python调用Windows .exe文件,传递参数并获取输出文件?
抱歉,我刚接触Python,关于子进程的文档我看得一头雾水!
我有一个Windows可执行文件,它可以把一种专有的文件格式转换成Geotiff格式。当我运行这个程序时,它会让我输入我想用的文件名,然后依次给我几个选项,比如我想做什么(选项6)、输出文件类型是什么(选项3)等等,最后还会让我输入一个输出文件名。我有大约2000张图片需要转换,所以我想把这个过程自动化。
我尝试了几种不同的方式:
subprocess.Popen('executable, input file, arguments, outputfile')
或者
prog = subprocess.call('executable',stdout=PIPE,stdin=PIPE,stederr=PIPE)
out, err = prog.communicate('filename\narguments\noutputfile')
或者
result = subprocess.check_output(['executable','inputfile','arguments','outputfile')
这些都是根据这个网站上其他问题的建议来的。虽然没有报错,但程序就是在那里运行,什么也不做。我应该使用什么命令来运行我的可执行文件,并带上正确的参数,以便保存Windows可执行文件生成的Geotiff输出呢?
谢谢!
2 个回答
你可以直接使用 os.system。下面是一个例子:
from os import system
system("Path\to\Application.exe input file arguments outputfile")
这个例子是来自 Python 2.7 的,但在 3.x 版本中也应该可以用。
通常,一个命令行工具可以通过命令行参数接收输入,但这个叫做 sir_util2 的工具却是通过 C 语言的运行时函数 fscanf
1 从用户输入中读取数据。像 call
、check_call
和 check_output
这些子进程的便利函数并不容易让你把输入发送到 stdin
。你应该直接使用 Popen
类,然后调用 communicate
方法。
我手动追踪了源文件 sir_util2.c 中的 fscanf
调用,得到了以下结果:
import subprocess
sir_util2_path = 'sir_util2.exe'
def sir_to_geotiff(infname, outfname, smin, smax, show_nodata):
show_nodata = int(show_nodata)
opt = 6 # convert to image
fmt = 3 # GeoTIFF
param = [infname, opt, fmt, smin, smax, show_nodata, outfname]
cmd = [sir_util2_path]
p = subprocess.Popen(cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
out, err = p.communicate('\n'.join(map(str, param)))
if p.returncode != 0:
raise subprocess.CalledProcessError(p.returncode,
cmd,
output=(out,err))
我使用了一个小测试程序,而不是编译原始源代码,所以实际程序的表现可能会有所不同。
#include <stdio.h>
int main()
{
int num;
float fnum;
char str[250];
fscanf(stdin, "%s", str);
printf("input filename: %s\n", str);
fscanf(stdin, "%d", &num);
printf("menu option: %d\n", num);
fscanf(stdin, "%d", &num);
printf("output format: %d\n", num);
fscanf(stdin, "%f", &fnum);
printf("min saturation: %f\n", fnum);
fscanf(stdin, "%f", &fnum);
printf("max saturation: %f\n", fnum);
fscanf(stdin, "%d", &num);
printf("show no-data: %d\n", num);
fscanf(stdin, "%s", str);
printf("output filename: %s\n", str);
return 1; /* force error */
}
我强制程序以非零的返回码退出。这样我就可以检查 CalledProcessError
:
try:
sir_to_geotiff('example.sir',
'example.tif',
30.0,
80.0,
True)
except subprocess.CalledProcessError as e:
print(e.output[0])
输出:
input filename: example.sir
menu option: 6
output format: 3
min saturation: 30.000000
max saturation: 80.000000
show no-data: 1
output filename: example.tif
1. 正如 J.F. Sebastian 在评论中提到的,程序可以直接通过 ReadConsoleInput
从控制台输入缓冲区读取,但幸运的是这个程序并没有这样做,它是通过 CRT 的 _getch
函数来实现的。