如何在wxPython中禁用调试断言消息或将消息重定向到控制台

时间:2014-07-29 13:34:49

标签: wxpython wxwidgets assert

当尝试在单独的线程中运行wxPython的GUI构造和事件循环时,我遇到一个问题,当应用程序关闭时,会出现调试警报消息,请参阅图像:

debug alert

有没有办法将弹出的消息重定向到控制台?或者只是禁用那些警报警告消息?

我发现有一个函数DisableAsserts(),但我不知道如何从python脚本调用这个函数,这个函数是从C ++导出的吗?

还有另一种函数app.SetAssertMode(),但我测试了它,发现它对禁用或重定向警报消息没有任何影响。

我希望你的建议能解决这个问题,谢谢。

BTW,详细描述了为什么我需要在一个单独的线程中运行wxPython可以找到alert message pops up when I close a console application if I run wxPython app.MainLoop() in a seperate thread - Google Groups

编辑: 我发现在GDB的python接口下使用单独的wxPython Gui线程是一个质量。我可以使用旧版本的wxPython2.8.12来避免调试警报消息。对于GDB,我需要在def invoke(self, arg, from_tty):中定义一个自定义命令,如果我键入自定义命令,将调用该命令。一旦我输入命令,就会运行一个新线程,并构造一些wxPython GUI,并将线程转到Mainloop。如果我关闭Gui Window,Thread的run函数刚刚完成,但由于某些未知原因,有时候,线程对象不会立即被破坏。如果我再次运行自定义命令,有时,GDB只是崩溃,或者显示一个新窗口,但我看到打印命令的内容将转到它自己的窗口,而不是GDB的stdout或stderr,请参见下面的屏幕截图。 some new wxPython stdout and stderr window jump up

我相信在一个单独的线程中使用wxPython GUI在这里仍然不太稳定。如果你想尝试,这是我的测试代码。

import gdb

import sys

import threading
from threading import Thread
import ctypes

# Used to guarantee to use at least Wx2.8
import wxversion
wxversion.ensureMinimal('2.8')

import matplotlib
matplotlib.use('WXAgg')
from matplotlib import pyplot as plt

# uncomment the following to use wx rather than wxagg
#matplotlib.use('WX')
#from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas

# comment out the following to use wx rather than wxagg
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas

from matplotlib.backends.backend_wx import NavigationToolbar2Wx

from matplotlib.figure import Figure


from numpy import arange, sin, pi

import wx

class CanvasFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self,None,-1,
                         'CanvasFrame',size=(550,350))

        self.SetBackgroundColour(wx.NamedColour("WHITE"))

        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0,3.0,0.01)
        s = sin(2*pi*t)

        self.axes.plot(t,s)
        self.canvas = FigureCanvas(self, -1, self.figure)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.add_toolbar()  # comment this out for no toolbar


    def add_toolbar(self):
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            # Mac platform (OSX 10.3, MacPython) does not seem to cope with
            # having a toolbar in a sizer. This work-around gets the buttons
            # back, but at the expense of having the toolbar at the top
            self.SetToolBar(self.toolbar)
        else:
            # On Windows platform, default window size is incorrect, so set
            # toolbar width to figure width.
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            # By adding toolbar in sizer, we are able to put it at the bottom
            # of the frame - so appearance is closer to GTK version.
            # As noted above, doesn't work for Mac.
            self.toolbar.SetSize(wx.Size(fw, th))
            self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        # update the axes menu on the toolbar
        self.toolbar.update()


    def OnPaint(self, event):
        self.canvas.draw()

class MyApp(wx.App):

    def OnInit(self):
        'Create the main window and insert the custom frame'
        frame = CanvasFrame()
        whnd = frame.GetHandle()
        # SW_SHOW = 5, so we force to set on the WS_VISIBLE window style, see below as a reference
        # Window Styles (Windows) - http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
        # ShowWindow function (Windows) - http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
        ctypes.windll.user32.ShowWindow(whnd, 5) 
        frame.Show(True)
        return True



class MyThread (threading.Thread):

    def __init__(self, thread_id = None, name = None, image = None):
        threading.Thread.__init__(self)
        self.thread_id = thread_id
        self.name = name
        self.image = image
        self.app = None
        self.start()

    def __del__(self):
        print "MyThrad dead"
        #ctypes.windll.user32.MessageBoxA(None, 'MyThread dead', 'Window title', 0)

    def run(self):
        self.app = MyApp(False)
        self.app.MainLoop()
        #ctypes.windll.user32.MessageBoxA(None, 'Main loop finish', 'Window title', 0)
        print "MyThread run() finish"

    def set_image(self, image):
        self.image = image
        print "image set/updated"


class PlotterCommand(gdb.Command):
    def __init__(self):
        super(PlotterCommand, self).__init__("plot",
                                             gdb.COMMAND_DATA,
                                             gdb.COMPLETE_SYMBOL)
        print "Constructor of Plotter object"
        self.thread1 = None
        sys.stdout.flush()

    def __del__( self ):  
        print 'Destructor of Plotter object' 
        sys.stdout.flush()


    def invoke(self, arg, from_tty):
        #args = gdb.string_to_argv(arg)
        # generally, we type "plot someVar" in the GDB commandline
        #v = gdb.parse_and_eval(args[0])
        # do something with the v object

        thread1 = MyThread(1, "Thread 1", None)

        print "Finish invoke plot command"
        sys.stdout.flush()

PlotterCommand()

将上面的代码保存为“my.py”,在GDB下调试时,可以输入命令source my.py来加载那些python代码,现在你有一个名为plot的新命令,你可以在GDB中键入plot,将显示一个wxPython窗口。您可以关闭窗口,再次键入plot,然后会出现问题。或者,您可以离开窗口,只需键入plot,您就会收到更多错误。

EDIT2 “stdout / stderr”窗口问题已修复,我可以通过self.app = MyApp(False)来禁用此日志窗口。

0 个答案:

没有答案