【问题标题】:subprocess.Popen give real-time feedback in pythonsubprocess.Popen 在 python 中提供实时反馈
【发布时间】:2014-03-04 23:38:31
【问题描述】:

我的 python 脚本中有以下命令运行一个命令行应用程序,该应用程序当前在后台“盲”运行。如果我从命令行、mac 或 PC 运行此命令,我会实时读取该应用程序的运行情况,因为它运行 40 分钟以上,并在运行时报告各种不同的信息。目前,正如我所说的那样,它会盲目运行,并在最后以 python 的读数为我提供所有信息,但我希望它本质上打开一个命令行并运行,以便我可以实时查看所有信息,但我可以'找不到办法做到这一点。这是我当前使用subprocess.Popen 的代码。还有其他方法吗?

command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s " + provider1 + " -v eXtreme"
        process = subprocess.Popen(command1, stdout=subprocess.PIPE, shell=True)

【问题讨论】:

标签: python command-line wxpython subprocess


【解决方案1】:

几年前我写过这篇文章,但我认为我的文章标题不太好:

基本上你需要重定向标准输出。我通常会这样做:

class RedirectText:
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl

    def write(self,string):
        self.out.WriteText(string)

然后在我实际的 wx 类中,我在 init 中执行类似的操作:

self.redir=RedirectText(log)
sys.stdout=self.redir

然后当你调用 subprocess 时,你会做类似下面的例子:

def pingIP(self, ip):
    proc = subprocess.Popen("ping %s" % ip, shell=True, 
                            stdout=subprocess.PIPE) 
    print
    while True:
        line = proc.stdout.readline()                        
        wx.Yield()
        if line.strip() == "":
            pass
        else:
            print line.strip()
        if not line: break
    proc.wait()

注意 wx.Yield() 调用。这允许 wxPython 在我们将行打印到 stdout 时进行更新,我们已将其重定向到文本控件。

这是一个排序示例:

import subprocess
import sys
import wx

class RedirectText:
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl

    def write(self,string):
        self.out.WriteText(string)

########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Test")
        panel = wx.Panel(self)
        log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100),
                          style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
        btn = wx.Button(panel, label="Run")
        btn.Bind(wx.EVT_BUTTON, self.onRun)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5)
        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
        panel.SetSizer(sizer)

        self.redir=RedirectText(log)
        sys.stdout=self.redir

    #----------------------------------------------------------------------
    def onRun(self, event):
        """"""
        command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s " + provider1 + " -v eXtreme"
        process = subprocess.Popen(command1, stdout=subprocess.PIPE, shell=True)
        while True:
            line = process.stdout.readline()
            wx.Yield()
            print line
            if not line:
                break
        process.wait()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    frame.Show()
    app.MainLoop()

【讨论】:

  • 感谢您的解决方案 Mike,我对 python 有点陌生,您能否详细说明您的解决方案,包括我将如何将其合并到我的代码中,抱歉。
  • 我真的不知道你打算如何调用你的命令,所以我只是在它周围写了一个小包装器,它使用一个按钮事件来执行它。
  • 迈克,你是明星,干杯。我收到 AttributeError:'Popen' 对象没有属性 'readline'。它在抱怨 line = process.readline()。我需要导入另一个模块吗?
  • 不,我只是打错了。它应该是 line = process.stdout.readline()。我也修复了这个例子。
  • 谢谢。它现在运行命令,但窗口中没有出现任何内容,我可以在通过空闲打开的终端窗口中看到我的应用程序在后台运行和报告,但 wx 窗口中仍然没有出现任何内容。请问有什么想法吗?
【解决方案2】:

我通过更改 Mikes 答案中的这一部分来开始工作,但现在唯一的问题是当应用程序结束并且输出完成打印行时,我的 python 冻结了。任何想法为什么?

def onRun(self, event):
    """"""
    command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s "
+ provider1 + " -v eXtreme"
    master, slave = pty.openpty()
    process = Popen(command1, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
    stdout = os.fdopen(master)
    while True:
        line = stdout.readline()
        wx.Yield()
        print line.rstrip()
        if not line:
            break
    process.wait()

【讨论】:

猜你喜欢
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
  • 2016-08-11
相关资源
最近更新 更多