通过 Python 与 Windows 控制台应用程序交互 [英] Interact with a Windows console application via Python

查看:33
本文介绍了通过 Python 与 Windows 控制台应用程序交互的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using python 2.5 on Windows. I wish to interact with a console process via Popen. I currently have this small snippet of code:

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()

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

I can write to stdin but can not read from stdout. Have I missed a step? I don't want to use p.communicate( "command" )[0] as it terminates the process and I need to interact with the process dynamically over time.

提前致谢.

推荐答案

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

Your problem here is that you are trying to control an interactive application.

stdout.read() 将继续读取,直到到达流、文件或管道的末尾.不幸的是,在交互式程序的情况下,管道仅在程序退出时关闭;如果您发送的命令不是 "quit",则永远不会.

stdout.read() will continue reading until it has reached the end of the stream, file or pipe. Unfortunately, in case of an interactive program, the pipe is only closed then whe program exits; which is never, if the command you sent it was anything other than "quit".

您将不得不使用 stdout.readline() 恢复到逐行读取子进程的输出,并且您最好有一种方法来判断程序何时准备好接受一个命令,当你向程序发出的命令完成后,你可以提供一个新的命令.对于像 cmd.exe 这样的程序,即使 readline() 也不够,因为指示可以发送新命令的行不会以换行符终止,所以必须逐字节分析输出.这是一个运行 cmd.exe 的示例脚本,查找提示,然后发出 direxit:

You will have to revert to reading the output of the subprocess line-by-line using stdout.readline(), and you'd better have a way to tell when the program is ready to accept a command, and when the command you issued to the program is finished and you can supply a new one. In case of a program like cmd.exe, even readline() won't suffice as the line that indicates a new command can be sent is not terminated by a newline, so will have to analyze the output byte-by-byte. Here's a sample script that runs cmd.exe, looks for the prompt, then issues a dir and then an 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

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

If the timing isn't important, and interactivity for a user isn't required, it can be a lot simpler just to batch up the calls:

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()

这篇关于通过 Python 与 Windows 控制台应用程序交互的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆