2009-07-14 106 views
7

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

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],因为它终止了进程,我需要随着时间的推移动态地与进程交互。

在此先感谢。

+0

您的代码似乎是正确的。从控制台执行时,console_app是否正常工作?它为command1返回什么? – luc 2009-07-14 13:04:21

+0

yes console_app在cmd.exe中运行时正常工作它只是根据提供的输入(有时是字符串)输出一些数字 – QAZ 2009-07-14 13:13:41

回答

0

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

编辑:对不起,误会。可能this问题可以帮到你吗?

+0

readline()也挂起。我可以确认控制台应用程序输出的数据应该在Python端正确读入。 – QAZ 2009-07-14 11:56:13

0

控制台应用程序是否有可能以某种方式缓冲其输出,以便在管道关闭时仅将其发送到标准输出?如果您有权访问控制台应用程序的代码,也许在一批输出数据可能有帮助后插入一次冲洗?

或者,它是否实际写入stderr而不是stdout出于某种原因?

只是再次查看您的代码并想到其他事情,我看到您正在发送“command \ n”。控制台应用程序可以简单地等待一个回车符而不是一个新行吗?也许控制台应用程序正在等待您在生成任何输出之前提交命令。

+0

谢谢,很好的建议。我不幸的是无法访问控制台应用程序的源代码。确认其写作stdout而不是stderr。 – QAZ 2009-07-14 12:21:02

0

这里有完全相同的问题。我钻进DrPython源代码,并偷走了wx.Execute()解决方案,它工作正常,特别是如果您的脚本已经在使用wx。我从来没有在Windows平台上找到正确的解决方案,但...

7

您的问题在于您正在尝试控制一个交互式应用程序。

stdout.read()将继续读取,直到它到达流,文件或管道的末尾。不幸的是,如果是交互式程序,管道只有在程序退出时才关闭;如果您发送的命令不是"quit"以外的其他命令,则永远不会。

您将不得不恢复为使用stdout.readline()逐行读取子进程的输出,并且您最好有一种方法来告诉程序何时准备好接受命令,以及何时发出命令到程序完成,你可以提供一个新的。在像cmd.exe这样的程序的情况下,即使readline()也不能满足,因为指示可以发送新命令的行不会被换行符终止,因此必须逐字节地分析输出。下面是运行cmd.exe一个示例脚本,找提示,然后发出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 

如果时间不是重要的,并且不需要交互的用户,也可以是很简单,只是为了批量调用:

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

您是否试图强制Windows结束行? 即

p.stdin.write('command1 \r\n') 
p.stdout.readline() 

UPDATE:

我刚刚检查了Windows CMD.EXE的解决方案,并与工作的ReadLine()。但它有一个问题Popen的stdout.readline 。因此,如果应用程序会返回一些没有结束的内容,那么您的应用程序将永久停留。

但有一个变通对于检查出:http://code.activestate.com/recipes/440554/

相关问题