【问题标题】:How to handle an executable requiring interactive responses?如何处理需要交互式响应的可执行文件?
【发布时间】:2014-06-23 06:56:35
【问题描述】:

我有一个名为 tsfoil2.exe 的可执行文件,我想在我的 python 环境中操作这个 .exe。 我在 Windows 7 上运行 Python 2.7.3 和 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 命令的代码行。 我也尝试将它包含在参数文件中,但这也不起作用。

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

是否可以使用 os.system 提供必要的“ENTER”,或者我应该切换到子进程,如果可以,我该如何构造类似于 os.system("tsfoil2.exe

我试过这个:

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找到。

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

【问题讨论】:

  • 确保文件末尾有一个空行。

标签: python windows subprocess os.system


【解决方案1】:

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

我在temp 文件的末尾没有看到空行。此外,您可能指的是'I:\\\n'——如果您想在输出中使用\,则需要在Python 字符串文字中使用'\\'

问题是 tsfoil2.exe 认为换行符是什么,例如 b'\r\n' 或只是 b'\n' 以及它希望从哪里接收它:来自标准输入 (getchar()) 或直接来自控制台 (getch())。

假设程序在 Windows 上期望来自标准输入的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)

工作原理

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

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

stdin=PIPE 告诉Popen 在调用它的父进程和新子进程(“tsfoil2.exe”)之间创建一个管道,并重定向子进程的标准输入。 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}
""")

我没有测试过。

【讨论】:

  • 第一个解决方案奏效了!您能否进一步说明它的工作方式?我自己也尝试过这种方式,但没有成功。我也尝试了第二种解决方案,但不是使用 .exe(即 C:\Users\THC0LQ\Desktop\TSFOIL\tsfoil2.exe)寻找所需的路径,而是搜索 rC;ßUsersßTHC0LQßDesktopßTSFOILßtsfoil2.exe,出于某种原因把给定的字符串弄乱了。
  • @ROIMaison:我添加了“它是如何工作的”部分。您应该为 SendKeys 函数使用原始字符串文字以避免误解反斜杠(注意:r"""...""")。手动输入 `\`,以防复制粘贴尝试粘贴外观相似的 Unicode 字符而不是反斜杠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多