Ich habe das pub/sub Mechanismus lesen ist ein Thread-safe Mittel auf eine GUI von einem Thread in Verbindung steht (https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/)WxPython GUI aufgrund abgefangene Ausnahme ‚NSRangeException‘ Absturz --- GELÖST
Das folgende Programm, die von einer größeren auf das Wesentliche des Problems reduziert wurde, stürzt nach einer Reihe von Schriften aus dem Thread auf den wx.TextCtrl
Bereich der GUI durch den Pub/Sub-Mechanismus ab. Zum Experimentieren mit mehreren Schreibraten kann dies in der time.sleep(x)
Anweisung geändert werden. Was auch immer x
ist, es stürzt ab (von mir getestet von 0,1 bis 100 Sekunden), es ist nicht eine Frage, wie oft der Thread in die GUI schreibt.
Grundsätzlich erstellt die GUI die Textsteuerung und abonniert einen Pub/Sub-Mechanismus. Der Thread schreibt regelmäßig in den Herausgeber. Es funktioniert gut, bis mit Ausnahme abstürzt:
2017-10-21 13:50:26.221 Python[20665:d07] An uncaught exception was raised
2017-10-21 13:50:26.222 Python[20665:d07] NSMutableRLEArray insertObject:range:: Out of bounds
2017-10-21 13:50:26.222 Python[20665:d07] ([…])
2017-10-21 13:50:26.223 Python[20665:d07] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray
insertObject:range:: Out of bounds'
*** First throw call stack:
([…]
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Die ‚außerhalb der Grenzen‘ bezieht sich wahrscheinlich auf einen Index, auf dem ich keinen Zugang von der Python-Code haben ... Ich bin nicht in der Lage, weiter zu gehen. Könnte jemand helfen?
Mit Python 2.7.12
| wxPython 3.0.2.0
Lauf Mac OS X 10.9.5
| auf der Plattform x86_64
Der Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__version__ = '04'
import sys
import threading
import time
import platform
try:
import wx
except ImportError:
raise ImportError ("The wxPython module is required to run this program")
try:
from pubsub import pub
except ImportError:
from wx.lib.pubsub import pub
class CrashFrame(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,id,title)
self.hor_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.textlogger = wx.TextCtrl(self, size=(520,110), style=wx.TE_MULTILINE | wx.VSCROLL, value="")
self.hor_sizer.Add(self.textlogger)
self.SetSizerAndFit(self.hor_sizer)
self.Show(True)
self.crashthread = SocketClientThread()
self.run()
def run(self):
self.logthistext('Using Python {} | wxPython {}'.format(sys.version.split()[0], wx.VERSION_STRING))
self.logthistext('Is thread running ? - %s' % self.crashthread.isAlive())
# Create a listener in the GUI form
pub.subscribe(self.logthistext, 'fromSocketListener')
def logthistext(self, msg):
self.textlogger.AppendText('{}\n'.format(msg)) # a good way to write on the text area
class SocketClientThread(threading.Thread):
def __init__(self):
super(SocketClientThread, self).__init__()
self.alive = threading.Event()
self.alive.set()
self.start() # thread will start at creation of the class instance
def run(self):
while self.alive.isSet():
data = 'A bunch of bytes'
pub.sendMessage('fromSocketListener', msg=data)
time.sleep(10) # or 0.1 or 100, whatever, it crashes
continue
if __name__ == '__main__':
app = wx.App()
frame = CrashFrame(None,-1,'Crash Program - v{}'.format(__version__))
app.MainLoop()
Danke Rolf. Es funktioniert gut. Groß ! Was ich verstehe, ist, dass der Pub/Sub-Mechanismus nicht threadsicher ist. CallAfter oder CallLater sind das eigentliche thread-sichere Mittel. –