wxPython,实时捕获子进程的输出

时间:2011-07-13 10:08:14

标签: python multithreading wxpython subprocess

我正在使用wxPython中的应用程序,它是命令行实用程序的GUI。在GUI中有一个文本控件,它应该显示应用程序的输出。我正在使用子进程启动shell命令,但是在完成之前我没有得到任何输出。

我尝试了几种解决方案,但似乎都没有。下面是我正在使用的代码(更新):

       def onOk(self,event):        
        self.getControl('infotxt').Clear()
        try:
            thread = threading.Thread(target=self.run)
            thread.setDaemon(True)
            thread.start()

        except Exception:
            print 'Error starting thread'    

    def run(self):    
        args = dict()
        # creating a command to execute...

        cmd = ["aplcorr", "-vvfile", args['vvfile'], "-navfile", args['navfile'], "-lev1file", args['lev1file'], "-dem", args['dem'], "-igmfile", args['outfile']]

        proc = subprocess.Popen(' '.join(cmd), shell=True, stdout=subprocess.PIPE, stderr.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()

class RedirectInfoText:
    """ Class to redirect stdout text """
    def __init__(self,wxTextCtrl):
        self.out=wxTextCtrl

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

class RedirectErrorText:
    """ Class to redirect stderr text """    
    def __init__(self,wxTextCtrl):
        self.out.SetDefailtStyle(wx.TextAttr())
        self.out=wxTextCtrl

    def write(self,string):
        self.out.SetDefaultStyle(wx.TextAttr(wx.RED))
        self.out.WriteText(string)

特别是我需要实时输出来创建进度条。

编辑:根据Mike Driscoll的建议改变了我的代码。它似乎有时工作,但大多数时候我得到以下错误之一:

  

(python:7698):Gtk-CRITICAL **:gtk_text_layout_real_invalidate:   断言`layout-> wrap_loop_count == 0'失败

  

(python:7893):Gtk-WARNING **:无效的文本缓冲区迭代器:要么   迭代器是未初始化的,或者是字符/ pixbufs / widgets   自迭代器创建以来,缓冲区已被修改。你必须   使用标记,字符数或行号来保留位置   跨缓冲区修改。您可以应用标签和插入标记   不会使迭代器失效,但会影响任何突变   'indexable'缓冲区内容(可以引用的内容)   字符偏移量)将使所有未完成的迭代器无效   分段错误(核心转储)

任何线索?

2 个答案:

答案 0 :(得分:2)

问题是因为您正在尝试wx.Yield并从运行该进程的线程的上下文更新输出窗口小部件,而不是从GUI线程进行更新。

  1. 由于您从一个线程运行该进程,因此不需要调用wx.Yield,因为您没有阻止GUI线程,因此任何挂起的UI事件都应该正常处理。

  2. 查看wx.PyOnDemandOutputWindow类,了解如何处理源自非GUI线程的打印件或其他输出的示例。

答案 1 :(得分:1)

这可能有点棘手,但我找到了一种方法,我在这里写到:http://www.blog.pythonlibrary.org/2010/06/05/python-running-ping-traceroute-and-more/

设置文本的重定向后,您只需要执行以下操作:

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

本文介绍了如何重定向文本。希望这会有所帮助!