Skip to main content
 首页 » 编程设计

python之从 wxpython 中的导入模块捕获标准输出并将其发送到 textctrl,而不阻塞 GUI

2025年05月04日23mengfanrong

有很多与此非常相似的问题,但我找不到专门适用于我正在尝试做的事情的问题。

我有一个模拟(用 SimPy 编写),我正在为其编写 GUI,模拟的主要输出是文本 - 从“打印”语句到控制台。现在,我认为最简单的方法是创建一个单独的模块 GUI.py,并将我的模拟程序导入其中:

import osi_model 

我希望所有的打印语句都被 GUI 捕获并出现在 Textctrl 中,这里有无数的例子,沿着这些行:

class MyFrame(wx.Frame): 
    def __init__(self, *args, **kwds): 
        <general frame initialisation stuff..> 
 
        redir=RedirectText(self.txtCtrl_1) 
        sys.stdout=redir 
 
class RedirectText: 
    def __init__(self,aWxTextCtrl): 
        self.out=aWxTextCtrl 
 
    def write(self,string): 
        self.out.WriteText(string) 

我也从“开始”按钮开始我的模拟:

def go_btn_click(self, event): 
    print 'GO' 
    self.RT = threading.Thread(target=osi_model.RunThis()) 
    self.RT.start() 

一切正常,模拟模块的输出由 TextCtrl 捕获,除了 GUI 锁定并变得无响应 - 我仍然需要它可以访问(至少有一个“停止”按钮) .我不确定这是否是我在这里创建新线程的拙劣尝试,但我假设在此过程的某个阶段将需要一个新线程。

人们建议使用 wx.CallAfter,但考虑到导入的模块不知道 wx,我不确定如何去做,而且我也不能现实地遍历整个模拟架构并更改所有打印wx.CallAfter 语句,任何从导入的模拟程序内部捕获 shell 的尝试都会导致程序崩溃。

有人对我如何才能最好地实现这一目标有任何想法吗?所以我真正需要的是让 TextCtrl 捕获所有控制台文本,同时 GUI 保持响应,并且所有文本仅来自导入的模块。

(另外,关于“停止”按钮的次要问题 - 仅终止模拟线程是否是一种不好的形式?)。

谢谢,

邓肯

请您参考如下方法:

我建议查看此 WX wiki article about long running tasks .

它专门解决了您正在使用“开始”按钮处理长时间运行的过程的情况。使用线程和空闲处理程序等不同技术给出了几个不同的示例。