首页 > 解决方案 > wxPython,关闭大型机时出现运行时和断言错误

问题描述

我有一个运行一些线程的 GUI,到目前为止只有四个。其中2个正在运行读取路由,从仪器到完成上传到SQL。另外两个正在监视上传到 SQL 数据库的数据。关闭大型机时,我得到一个运行时错误,它们都更新了 GUI。

Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\ACAS\PycharmProjects\ACAS\Main\GUI\panels\hygrometer_panel.py", line 42, in run
    wx.PostEvent(self.wxObject, ResultEvent(self.worker.read()))
RuntimeError: wrapped C/C++ object of type hygrometer has been deleted

我尝试过使用 wx.CallAfter 行。但是该错误仅更改为断言错误。

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\ACAS\PycharmProjects\ACAS\Main\GUI\panels\acquisition_panel.py", line 20, in run
    self.method()
  File "C:\Users\ACAS\PycharmProjects\ACAS\Main\GUI\panels\acquisition_panel.py", line 73, in ccn_status_method
    wx.CallAfter(self.ccn_status.SetLabel, 'RUNNING')
  File "C:\Python27\lib\site-packages\wx\core.py", line 3254, in CallAfter
    assert app is not None, 'No wx.App created yet'
AssertionError: No wx.App created yet

这里有一些线程方法。第一的

class TestThread(Thread):
    def __init__(self, wxObject):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self.wxObject = wxObject
        self.worker = workers.hygrometer_worker()
        self.start()  # start the thread

    def run(self):
        """Run Worker Thread."""
        # This is the code executing in the new thread.
        while True:
            wx.PostEvent(self.wxObject, ResultEvent(self.worker.read()))
            time.sleep(1)

第二

class TestThread(Thread):
    def __init__(self, method):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self.method = method
        self.start()  # start the thread

    def run(self):
        """Run Worker Thread."""
        # This is the code executing in the new thread.
        while True:
            self.method()
            time.sleep(1)

这发送方法完成所有工作,

    def update_display(self):
        data = self.worker.read()
        index = data.index.values[0]
        wx.CallAfter(self.current_ss_value.SetLabel, str(data.at[index, 'Current SS']))
        wx.CallAfter(self.stage_value.SetLabel, str(data.at[index, '1st Stage Mon']))
        wx.CallAfter(self.concentration_value.SetLabel, str(data.at[index, 'CCN Number Conc']))
        wx.CallAfter(self.delta_value.SetLabel, str(data.at[index, 'Delta T']))
        wx.CallAfter(self.cmd_value.SetLabel, str(data.at[index, 'CMD']))
        wx.CallAfter(self.gmd_values.SetLabel, str(data.at[index, 'GMD']))

我似乎真的没有错误。我尝试过不同的东西。

标签: multithreadingpython-2.7user-interfacewxpython

解决方案


self.wxObject您可以在尝试使用它之前确保它仍然存在,方法是使用if. 如果 C++ 对象已被销毁,则小部件类有一个__int____bool__返回。False所以,像这样:

    if self.wxObject:
        wx.PostEvent(self.wxObject, ...)

对于wx.App错误,您也可以使用它进行测试,wx.GetApp()并确保它不在None使用之前wx.CallAfter。或者您可以将工作线程的启动延迟到创建应用程序对象之后。

关于您的代码的另一条评论:我建议不要连续发布多个wx.CallAfters,每个都进行单独的 UI 更新。wx.CallAfter将这些语句移动到一个新方法中,然后使用它来调用该方法要好得多。这种方式效率更高,但更重要的是,它避免了由于事件系统的实现方式以及其中一些 CallAfters 在较早的事件返回之前执行的可能性而产生的问题。


推荐阅读