如何从Python调用Windows .exe文件,传递参数并获取输出文件?

1 投票
2 回答
3099 浏览
提问于 2025-04-18 01:23

抱歉,我刚接触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 个回答

0

你可以直接使用 os.system。下面是一个例子:

    from os import system
    system("Path\to\Application.exe input file arguments outputfile")

这个例子是来自 Python 2.7 的,但在 3.x 版本中也应该可以用。

2

通常,一个命令行工具可以通过命令行参数接收输入,但这个叫做 sir_util2 的工具却是通过 C 语言的运行时函数 fscanf1 从用户输入中读取数据。像 callcheck_callcheck_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 函数来实现的。

撰写回答