[英]wxPython, capturing an output from subprocess in real-time
我正在开发 wxPython 中的应用程序,这是一个命令行实用程序的 GUI。 在 GUI 中有一个文本控件,它应该显示来自应用程序的 output。 我正在使用子进程启动 shell 命令,但在它完成之前我没有得到任何 output 。
我尝试了几种解决方案,但似乎都没有奏效。 以下是我目前正在使用的代码(更新):
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)
特别是我将需要实时 output 来创建进度条。
编辑:根据 Mike Driscoll 的建议,我更改了代码。 它有时似乎有效,但大多数时候我遇到以下错误之一:
(python:7698): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: 断言 `layout->wrap_loop_count == 0' 失败
或者
(python:7893):Gtk-WARNING **:无效的文本缓冲区迭代器:迭代器未初始化,或者缓冲区中的字符/pixbufs/widgets自迭代器创建以来已被修改。 您必须使用标记、字符编号或行号来跨缓冲区修改保留 position。 您可以在不使迭代器失效的情况下应用标记和插入标记,但是任何影响“可索引”缓冲区内容(可以通过字符偏移量引用的内容)的突变都会使所有未完成的迭代器失效分段错误(核心转储)
有什么线索吗?
问题是因为您正在尝试 wx.Yield 并从运行进程的线程的上下文中更新 output 小部件,而不是从 GUI 线程进行更新。
由于您是从线程运行进程,因此不需要调用 wx.Yield,因为您没有阻塞 GUI 线程,因此任何未决的 UI 事件都应该正常处理。
查看 wx.PyOnDemandOutputWindow class 以了解如何处理源自非 GUI 线程的打印或其他 output 的示例。
这可能有点棘手,但我想出了一种方法,我在这里写过: http://www.blog.pythonlibrary.org/2010/06/05/python-running-ping-traceroute-and-更多的/
设置文本的重定向后,您只需要执行以下操作:
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()
这篇文章也展示了如何重定向文本。 希望这会有所帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.