通过Python与Windows控制台应用程序交互

QAZ*_*QAZ 7 python windows

我在Windows上使用python 2.5.我希望通过Popen与控制台进程进行交互.我目前有这小段代码:

p = Popen( ["console_app.exe"], stdin=PIPE, stdout=PIPE )
# issue command 1...
p.stdin.write( 'command1\n' )
result1 = p.stdout.read() # <---- we never return here
# issue command 2...
p.stdin.write( 'command2\n' )
result2 = p.stdout.read()
Run Code Online (Sandbox Code Playgroud)

我可以写stdin但无法从stdout读取.我错过了一步吗?我不想使用p.communicate("command")[0],因为它终止了进程,我需要随着时间的推移动态地与进程交互.

提前致谢.

rix*_*rrr 7

您的问题是您正在尝试控制交互式应用程序.

stdout.read()将继续读取,直到它到达流,文件或管道的末尾.不幸的是,在交互式程序的情况下,只有当程序退出时才关闭管道; 从来没有,如果你发送它的命令不是"quit".

您将不得不恢复使用逐行读取子进程的输出stdout.readline(),并且您最好有办法告诉程序何时准备接受命令,以及何时完成对程序发出的命令你可以提供一个新的.在类似程序的情况下cmd.exe,甚至readline()不够,因为指示可以发送新命令的行不会被换行终止,因此必须逐字节地分析输出.这是一个运行的示例脚本cmd.exe,查找提示,然后发出a dir然后发出exit:

from subprocess import *
import re

class InteractiveCommand:
    def __init__(self, process, prompt):
        self.process = process
        self.prompt  = prompt
        self.output  = ""
        self.wait_for_prompt()

    def wait_for_prompt(self):
        while not self.prompt.search(self.output):
            c = self.process.stdout.read(1)
            if c == "":
                break
            self.output += c

        # Now we're at a prompt; clear the output buffer and return its contents
        tmp = self.output
        self.output = ""
        return tmp

    def command(self, command):
        self.process.stdin.write(command + "\n")
        return self.wait_for_prompt()

p      = Popen( ["cmd.exe"], stdin=PIPE, stdout=PIPE )
prompt = re.compile(r"^C:\\.*>", re.M)
cmd    = InteractiveCommand(p, prompt)

listing = cmd.command("dir")
cmd.command("exit")

print listing
Run Code Online (Sandbox Code Playgroud)

如果时间不重要,并且不需要用户的交互性,那么批量调用可能会简单得多:

from subprocess import *

p = Popen( ["cmd.exe"], stdin=PIPE, stdout=PIPE )
p.stdin.write("dir\n")
p.stdin.write("exit\n")

print p.stdout.read()
Run Code Online (Sandbox Code Playgroud)

  • 如果是"cmd.exe",您可以自定义提示以使处理更容易.例如,使用`cmd.exe/k提示符$ g $ g $ g $ _`会将提示更改为`>>> \n`,以便您可以删除模式匹配并再次使用readline(). (2认同)

Rob*_*ssa 0

我想你可能想尝试使用 readline() 代替?

编辑:抱歉,误会了。

也许这个问题可以帮助你?