TextCtrl在wxPython中提供了一个超出范围的异常

时间:2013-06-22 00:31:53

标签: python macos wxpython

我是WX的新手,所以我决定制作一个程序,根据外部输入定期向屏幕写出一行文字。该程序的基础包含一个基本窗口,其中多行文本控件覆盖整个窗口。我在框架中唯一的另一种方法是打印出方法listen_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)

从另一个线程定期调用listen事件。一切似乎都没问题,程序可行,但是,每隔一段时间(比我想的更频繁)我得到一个大量的转储让我想起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

是什么给出的?我找不到这些错误的押韵或原因。有时它适用于连续几对,然后崩溃。有时它会在第一时间崩溃。我是否错误地实现了文本控制框?

2 个答案:

答案 0 :(得分:2)

这可能是或可能不是你的崩溃的原因,但如果肯定会导致崩溃,并且它们可能正是你所看到的那种崩溃(有时候它会起作用,有时会失败,有时会起作用)一段时间然后突然失败,即使没有任何可见的变化......)。

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

有几种不同的方法:

  • 使用PostEvent为主UI线程排队事件(在事件处理程序中使用实际的UI更改代码)。
  • 使用CallAfterCallLater来安排在主UI线程上调用函数(在该函数中使用实际的UI更改代码)。
  • 使用pubsub框架。
  • 使用一些外部到wx机制(例如,来自threading模块,或管道或其他)来表示主UI线程。
  • 以上不止一个。

(在幕后,CallAfterPostEvent的包装,CallLater是计时器加CallAfter的包装,计时器和threading两者都是围绕相同的本机线程API的包装器,依此类推,所以这并不像看起来那么多不同的可能性......)


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

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

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

我不认为这会导致你的问题。因为self在创建之后永远不会改变属性,并且(假设你正在使用CPython,或者其他一些带有GIL的Python实现),没有任何其他可能会以非原子方式发生可能影响你的东西,你将会离开在这里。但是,如果您不理解为什么您的代码(wx调用除外)是线程安全的,那么您不应该依赖它。

答案 1 :(得分:0)

我运行程序时遇到了同样的问题。如果您能查看我的代码并建议进行一些更改,将会非常有帮助。我在这里发布了我的问题:  Application crashed while giving input to wxPython GUI。谢谢你的帮助。