TextCtrl在wxPython中提供越界异常

TextCtrl在wxPython中提供越界异常,python,macos,wxpython,Python,Macos,Wxpython,我是WX新手,所以我决定制作一个程序,根据外部输入定期向屏幕写入一行文本。程序的基础包含一个基本窗口,多行文本控件覆盖整个窗口。我在框架中唯一的另一种方法是将方法listen\u event得到的内容打印出来,作为多行TextCtrl的新行。就这样,代码如下: class Frame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, title = 'Program',

我是WX新手,所以我决定制作一个程序,根据外部输入定期向屏幕写入一行文本。程序的基础包含一个基本窗口,多行文本控件覆盖整个窗口。我在框架中唯一的另一种方法是将方法
listen\u event
得到的内容打印出来,作为多行TextCtrl的新行。就这样,代码如下:

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None,
            title = 'Program',
            size = (640, 480),
            style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX)
        panel = wx.Panel(self)
        self.textArea = wx.TextCtrl(parent = panel,
            id = -1,
            pos = (0, 0),
            size = (-1, -1),
            style = wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_AUTO_URL)

    def listen_event(self, data):
        self.textArea.AppendText(data)
侦听事件从另一个线程定期调用。一切似乎都很好,程序运行正常,但是,每隔一段时间(比我希望的更频繁),我就会收到大量的ObjectiveC错误消息:

2013-06-21 20:11:47.820 Python[85638:420b] An uncaught exception was raised
2013-06-21 20:11:47.821 Python[85638:420b] NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds
2013-06-21 20:11:47.824 Python[85638:420b] (
    0   CoreFoundation                      0x00007fff92e2bf56 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff8fc0bd5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff92e2bd8a +[NSException raise:format:arguments:] + 106
    3   CoreFoundation                      0x00007fff92e2bd14 +[NSException raise:format:] + 116
    4   Foundation                          0x00007fff8fe93b20 -[NSMutableRLEArray replaceObjectsInRange:withObject:length:] + 132
    5   AppKit                              0x00007fff8d3e33f8 -[NSLayoutManager addTemporaryAttribute:value:forCharacterRange:] + 500
    6   AppKit                              0x00007fff8d7f9716 -[NSTextView _markTextEditedForRange:] + 1025
    7   AppKit                              0x00007fff8d7f8392 -[NSTextView insertText:replacementRange:] + 2400
    8   AppKit                              0x00007fff8d7f7a25 -[NSTextView insertText:] + 320
    9   libwx_osx_cocoau-2.9.4.0.0.dylib    0x0000000101953b71 _ZN19wxNSTextViewControl9WriteTextERK8wxString + 257
    10  libwx_osx_cocoau-2.9.4.0.0.dylib    0x00000001018bfb53 _ZN11wxTextEntry9WriteTextERK8wxString + 67
    11  _core_.so                           0x00000001014dec57 _wrap_TextEntryBase_AppendText + 199
    12  Python                              0x00000001000c1112 PyEval_EvalFrameEx + 22626
    13  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    14  Python                              0x00000001000c0b6a PyEval_EvalFrameEx + 21178
    15  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    16  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    17  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    18  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    19  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    20  Python                              0x00000001000c0b6a PyEval_EvalFrameEx + 21178
    21  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    22  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    23  Python                              0x000000010003da80 function_call + 176
    24  Python                              0x000000010000c5e2 PyObject_Call + 98
    25  Python                              0x000000010001ebcb instancemethod_call + 363
    26  Python                              0x000000010000c5e2 PyObject_Call + 98
    27  Python                              0x00000001000ba5f7 PyEval_CallObjectWithKeywords + 87
    28  Python                              0x0000000100100a63 t_bootstrap + 67
    29  libsystem_c.dylib                   0x00007fff933008bf _pthread_start + 335
    30  libsystem_c.dylib                   0x00007fff93303b75 thread_start + 13
)
2013-06-21 20:11:47.825 Python[85638:420b] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff92e2bf56 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff8fc0bd5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff92e2bd8a +[NSException raise:format:arguments:] + 106
    3   CoreFoundation                      0x00007fff92e2bd14 +[NSException raise:format:] + 116
    4   Foundation                          0x00007fff8fe93b20 -[NSMutableRLEArray replaceObjectsInRange:withObject:length:] + 132
    5   AppKit                              0x00007fff8d3e33f8 -[NSLayoutManager addTemporaryAttribute:value:forCharacterRange:] + 500
    6   AppKit                              0x00007fff8d7f9716 -[NSTextView _markTextEditedForRange:] + 1025
    7   AppKit                              0x00007fff8d7f8392 -[NSTextView insertText:replacementRange:] + 2400
    8   AppKit                              0x00007fff8d7f7a25 -[NSTextView insertText:] + 320
    9   libwx_osx_cocoau-2.9.4.0.0.dylib    0x0000000101953b71 _ZN19wxNSTextViewControl9WriteTextERK8wxString + 257
    10  libwx_osx_cocoau-2.9.4.0.0.dylib    0x00000001018bfb53 _ZN11wxTextEntry9WriteTextERK8wxString + 67
    11  _core_.so                           0x00000001014dec57 _wrap_TextEntryBase_AppendText + 199
    12  Python                              0x00000001000c1112 PyEval_EvalFrameEx + 22626
    13  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    14  Python                              0x00000001000c0b6a PyEval_EvalFrameEx + 21178
    15  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    16  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    17  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    18  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    19  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    20  Python                              0x00000001000c0b6a PyEval_EvalFrameEx + 21178
    21  Python                              0x00000001000c1ebe PyEval_EvalFrameEx + 26126
    22  Python                              0x00000001000c2d29 PyEval_EvalCodeEx + 2137
    23  Python                              0x000000010003da80 function_call + 176
    24  Python                              0x000000010000c5e2 PyObject_Call + 98
    25  Python                              0x000000010001ebcb instancemethod_call + 363
    26  Python                              0x000000010000c5e2 PyObject_Call + 98
    27  Python                              0x00000001000ba5f7 PyEval_CallObjectWithKeywords + 87
    28  Python                              0x0000000100100a63 t_bootstrap + 67
    29  libsystem_c.dylib                   0x00007fff933008bf _pthread_start + 335
    30  libsystem_c.dylib                   0x00007fff93303b75 thread_start + 13
)
terminate called throwing an exception

有什么好处?我找不到这些错误的押韵或原因。有时,它对一对夫妇连续工作,然后崩溃。有时它会在第一次运行时崩溃。我是否错误地实现了文本控制框?

这可能是您崩溃的原因,也可能不是,但如果确实会导致崩溃,并且很可能正是您看到的那种崩溃(有时有效,有时失败,有时有效一段时间,然后突然失败,即使没有任何可见的变化…)

不能从其他线程调用对UI对象进行操作的方法。每次从另一个线程调用
self.textArea.AppendText
,都有可能导致崩溃,或者更有趣的是,会破坏内存或其他资源,导致以后崩溃

有几种不同的解决方法:

  • 用于将主UI线程的事件排队(事件处理程序中的实际UI更改代码)
  • 使用或调度要在主UI线程上调用的函数(该函数中的实际UI更改代码)
  • 使用
    pubsub
    框架
  • 使用一些wx机制的外部(例如,从
    线程
    模块,或管道,或其他)向主UI线程发送信号
  • 以上不止一项
(在封面下,
CallAfter
是围绕
PostEvent
的包装,而
CallLater
是围绕计时器加
CallAfter
的包装,计时器和
threading
都是围绕同一个本机线程API的包装,依此类推,所以这并不像看上去那么多不同的可能性…)


无论如何,对代码最微不足道的更改是:

def listen_event(self, data):
    wx.CallAfter(self.textArea.AppendText, data)

最重要的是,您违反了多线程编程的第一条规则:共享可变对象只能在锁下访问


我不认为这是你的问题所在。由于
self
在创建之后将永远不会更改属性,并且(假设您使用的是CPython,或者其他一些带有GIL的Python实现),没有任何其他非原子性的情况会影响您,因此您可以在这里逃脱。但是,如果您不理解为什么代码(除了
wx
调用)是线程安全的,您就不应该指望它。

我在运行程序时也遇到了同样的问题。这将是非常有帮助的,如果你能看看我的代码,并建议一些修改要做。我已经在这里发布了我的问题:
. 感谢您的帮助。

它之所以让您想起ObjC崩溃转储,是因为它是ObjC崩溃转储<代码> WXPython 是围绕每个平台本地窗口对象的C++包装器的Python包装器,在MAC上,这意味着Objc。如您所见,实际崩溃是ObjC代码中的一个
NSException