在GUI中运行Python脚本并将标准输出/标准错误重定向到wx.TextCtrl中的线程中

2024-06-06 19:22:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图编写一个GUI,读取python脚本的设置,然后生成脚本并运行它。这个脚本可能需要几十分钟才能运行,所以为了不阻塞GUI和挫败用户,我在一个单独的线程中运行它。在此之前,我使用了一个单独的类来重定向标准输出以及标准误差一个文本控制。除了GUI在执行过程中被阻塞外,这一切都很好。在

使用重定向类从线程运行脚本仍然会阻塞GUI。为了不阻止GUI,我需要关闭重定向。全部标准输出/错误然后从脚本和gui进入控制台。在

这是重定向的类以及我如何调用它。在

# For redirecting stdout/stderr to txtctrl.
class RedirectText(object):
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl

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

self.redir=RedirectText(self.bottom_text)
sys.stdout=self.redir
sys.stderr=self.redir
sys.stdin=self.redir

我尝试过从线程到GUI使用某种通信类,但没有成功。也就是说,GUI仍然会被阻塞。在

对于这个问题,有没有人有一些提示或解决方案,即在不阻塞GUI的情况下,将stdout/err从脚本传递到GUI?在


Tags: self脚本标准stringdefstderrstdoutsys
2条回答

是的。从线开始,使用wx.CallAfter公司以线程安全的方式将文本发送到GUI。然后它可以获取文本并显示它。另一种方法是使用子流程并与之通信。这里有一个例子:

{a1}

本文评论中还列出了一些方法:

http://www.blog.pythonlibrary.org/2009/01/01/wxpython-redirecting-stdout-stderr/

不幸的是,当时我的评论系统并没有很好地处理缩进。在

我成功使用的另一个解决方案是使用python日志记录,而不是stdout/stderr。为了做到这一点,您需要编写一个扩展的子类日志处理程序,以自定义要在中显示的字体和文本颜色wx.TextCtrl在您的wx应用程序中:

import logging
from logging import Handler

class WxHandler(Handler):
    def __init__(self, logCtrl):
        """
        Initialize the handler.
        logCtrl = an instance of wx.TextCtrl
        """
        self.logCtrl = logCtrl
        Handler.__init__(self)

    def flush(self):
        pass

    def emit(self, record):
        """
        Emit a record.

        If a formatter is specified, it is used to format the record.
        The record is then written to the stream with a trailing newline.  If
        exception information is present, it is formatted using
        traceback.print_exception and appended to the stream.  If the stream
        has an 'encoding' attribute, it is used to encode the message before
        output to the stream.
        """
        try:
            lastPos = self.logCtrl.GetLastPosition()
            msg = self.format(record)
            self.logCtrl.WriteText(msg)
            self.logCtrl.WriteText('\r\n')
            f = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL, False, u'Arial', wx.FONTENCODING_ISO8859_1)
            if record.levelno == logging.INFO:
                textColour = wx.Colour(0, 0, 205)
            elif record.levelno == logging.WARN: 
                textColour = wx.Colour(250, 128, 114)
            elif record.levelno >= logging.ERROR:
                textColour = wx.Colour(220, 20, 60)
            else:
                textColour = wx.Colour(0, 0, 0)
            self.logCtrl.SetStyle(lastPos, lastPos + len(msg), wx.TextAttr(textColour, wx.NullColour, f))
        except:
            self.handleError(record)

要配置记录器:

^{pr2}$

最后,要将文本控件绑定到日志输出:

self.logCtrl = wx.TextCtrl(self, -1, "", size=(600, 200), style=wx.TE_MULTILINE|wx.TE_RICH2)
wxLoggingHelper.configureWxLogger(self.logCtrl, logging.DEBUG)

相关问题 更多 >