如何处理需要交互式响应的可执行文件?

时间:2014-05-06 15:10:31

标签: python windows subprocess os.system

我有一个名为tsfoil2.exe的可执行文件,我想在我的python环境中运行这个.exe。 我正在运行Python 2.7.3,在Windows 7上使用Spyder 2.1.11。

为了操作.exe,它需要一些输入,默认硬盘('I:\'),输出文件的名称('test')和输入文件的名称('SC20610。 INP')。

我的一位同事建议我使用os.system,并为其提供一个包含所有参数的临时输入文件。

f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 

然后我以下列方式为.exe文件提供参数:

os.system("tsfoil2.exe < temp")

这一切都有效,但程序需要'ENTER'才能关闭。出于某种原因,.exe一再要求'按ENTER键退出'。甚至,当我按下Spyder控制台中的回车键时,程序也不会终止。

有没有办法将'ENTER'键作为.exe的交互式输入? 我试图使用SendKeys类,但由于程序没有终止,它没有到达包含SendKeys命令的代码行。 我也尝试将它包含在arguments-file中,但这也不起作用。

此外,我还发现切换到subprocesses命令可能是有益的,因为它可能会给我更多的执行命令,但我无法使用输入文件运行可执行文件。

是否可以使用os.system提供必要的“ENTER”,或者我应该切换到子进程,如果是这样,我该如何构造一个类似于os.system的方法(“tsfoil2.exe&lt” ; temp“)我现在正在使用。

我试过这个:

import subprocess as sub
f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 
proc=sub.Popen(["tsfoil2.exe","temp"], shell=True)

和这个

import subprocess as sub
p=sub.Popen('tsfoil2.exe')
p.communicate(input='I:' )

但是,该计划没有回应所给出的论点。

MWE:

import os
f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 

os.system("tsfoil2.exe < temp")

该程序都可以通过http://www.dept.aoe.vt.edu/~mason/Mason_f/tsfoil2.exe找到,输入文件可以通过http://www.dept.aoe.vt.edu/~mason/Mason_f/SC20610.inp找到。

我希望一切都清楚,你可以帮助我。

1 个答案:

答案 0 :(得分:1)

'Press the ENTER key to exit'表示程序需要换行符。

我在temp文件的末尾看不到空白行。另外,您可能需要'I:\\\n' - 如果您希望输出中有'\\',则需要在Python字符串文字中使用\

问题是tsfoil2.exe考虑换行符,例如b'\r\n'或仅b'\n'以及它希望从哪里接收它:来自stdin(getchar())或直接来自控制台(getch())。

假设程序在Windows上需要来自stdin的b'\r\n'

import os
from subprocess import CalledProcessError, Popen, PIPE

cmd = "tsfoil2.exe"
input_data = os.linesep.join(['I:\\', 'test', 'SC20610.inp', os.linesep])
p = Popen(cmd, stdin=PIPE, bufsize=0)
p.communicate(input_data.encode('ascii'))
if p.returncode != 0:
   raise CalledProcessError(p.returncode, cmd)

如何运作

Windows上的

os.linesep == "\r\n""\n".join(["a", "b"]) == "a\nb"

每个进程可能有三个standard streams:stdin,stdout,stderr。在Python中,它们表示为sys.stdinsys.stdoutsys.stderr。您可以从stdin读取输入并写入stdout,stderr,例如,{stidr}从stdin读取input函数,默认情况下print写入stdout。 stderr可能用于编写错误消息。

stdin=PIPE告诉Popen在调用它的父进程和新的子进程(&#34; tsfoil2.exe&#34;)之间创建一个管道,并重定向子进程&#39;标准输入。 p.communicate(data)将数据写入p.stdin,关闭它并等待子进程完成。 p.returncode包含子进程的退出状态。通常非零状态意味着失败。

它模拟shell管道而不实际生成shell:

$ echo input data | tsfoil2.exe

如果直接从控制台输入,您可以尝试SendKeys module或其纯Python实现SendKeys-ctypes

from SendKeys import SendKeys

SendKeys(r"""
    {LWIN}
    {PAUSE .25}
    r
    C:\Path\To\tsfoil2.exe{ENTER}
    {PAUSE 1}
    I:\{ENTER}
    {PAUSE 1}
    test{ENTER}
    {PAUSE 1}
    SC20610.inp{ENTER}
    {PAUSE 1}
    {ENTER}
""")

我还没有测试过它。