关闭大型机时的 wxPython、运行时和断言错误
wxPython, Runtime and Assertion Error when closing mainframe
我有一个 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']))
我好像真的没有出错。我尝试过不同的东西。
您可以确保 self.wxObject
在尝试使用它之前仍然存在,方法是使用 if
对其进行测试。如果 C++ 对象已经被销毁,小部件 类 有一个 __int__
或 __bool__
return False
。所以,像这样:
if self.wxObject:
wx.PostEvent(self.wxObject, ...)
对于 wx.App
错误,您也可以使用 wx.GetApp()
对其进行测试,并在使用 wx.CallAfter
之前确保它不是 None
。或者您可以延迟工作线程的启动,直到创建应用程序对象之后。
关于您的代码的更多评论:我建议 不要 连续发布多个 wx.CallAfters
,每个都进行单独的 UI 更新。最好将这些语句移至新方法,然后使用 wx.CallAfter
仅调用该方法。这样效率更高,但更重要的是,它避免了事件系统的实现方式以及其中一些 CallAfter 在较早的 returns.
之前执行的可能性引起的问题
我有一个 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']))
我好像真的没有出错。我尝试过不同的东西。
您可以确保 self.wxObject
在尝试使用它之前仍然存在,方法是使用 if
对其进行测试。如果 C++ 对象已经被销毁,小部件 类 有一个 __int__
或 __bool__
return False
。所以,像这样:
if self.wxObject:
wx.PostEvent(self.wxObject, ...)
对于 wx.App
错误,您也可以使用 wx.GetApp()
对其进行测试,并在使用 wx.CallAfter
之前确保它不是 None
。或者您可以延迟工作线程的启动,直到创建应用程序对象之后。
关于您的代码的更多评论:我建议 不要 连续发布多个 wx.CallAfters
,每个都进行单独的 UI 更新。最好将这些语句移至新方法,然后使用 wx.CallAfter
仅调用该方法。这样效率更高,但更重要的是,它避免了事件系统的实现方式以及其中一些 CallAfter 在较早的 returns.