Program gives different errors on different runs, I don't know why

33 views
Skip to first unread message

Patrick Maher

unread,
Mar 26, 2012, 2:51:26 PM3/26/12
to wxpytho...@googlegroups.com
I'm trying to write a program that moves a highlight through the phrases of a text at specified times. My program works for a while but then stops. How far it gets, and what error it reports, varies from run to run, and I don't know what's causing this. Perhaps it has something to do with my use of threading.Timer. I've attached a fairly minimal version of the program that demonstrates the problem and below I've copied the different outputs from three different runs of this sample program. I'd be grateful if someone could tell me what I'm doing wrong. I'm using wxPython 2.8.11.0 on Python 2.7 and Windows 7.

Thanks,
Patrick Maher


Results from three successive runs of advancephrase.py:

FIRST:

selected phrase 0
unseleted phrase 0
selected phrase 1
unseleted phrase 1
selected phrase 2

[Windows then popped up a window saying the program had stopped working.]

SECOND:

selected phrase 0
unseleted phrase 0
selected phrase 1
unseleted phrase 1
selected phrase 2
Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 530, in __bootstrap_inner
    self.run()
  File "C:\Python27\lib\threading.py", line 734, in run
    self.function(*self.args, **self.kwargs)
  File "C:\Monceau\test\advancephrase.py", line 46, in <lambda>
    timer = threading.Timer(duration/1000.0,lambda: self.advanceselection(None))
  File "C:\Monceau\test\advancephrase.py", line 40, in advanceselection
    self.SetStyle(self.ranges[self.phrasenum-1], self.normalstyle) #Unselect previously selected phrase
  File "C:\Python27\lib\site-packages\wx-2.8-msw-unicode\wx\richtext.py", line 2531, in SetStyle
    return _richtext.RichTextCtrl_SetStyle(*args, **kwargs)
PyAssertionError: C++ assertion "uiIndex < m_nCount" failed at ..\..\include\wx/dynarray.h(813) in w
xBaseArrayInt::Item()

THIRD:

selected phrase 0
unseleted phrase 0
selected phrase 1
unseleted phrase 1
selected phrase 2
unseleted phrase 2
selected phrase 3
unseleted phrase 3
selected phrase 4
unseleted phrase 4
Unhandled exception in thread started by <bound method _Timer.__bootstrap of <_Timer(Thread-5, stopp
ed 18932)>>
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 503, in __bootstrap
    self.__bootstrap_inner()
  File "C:\Python27\lib\threading.py", line 543, in __bootstrap_inner
    (self.name, _format_exc()))
  File "C:\Python27\lib\traceback.py", line 144, in format_exception
    list = list + format_exception_only(etype, value)
TypeError: 'list' object is not callable


advancephrase.py

Tim Roberts

unread,
Mar 26, 2012, 3:17:43 PM3/26/12
to wxpytho...@googlegroups.com
Patrick Maher wrote:
> I'm trying to write a program that moves a highlight through the
> phrases of a text at specified times. My program works for a while but
> then stops. How far it gets, and what error it reports, varies from
> run to run, and I don't know what's causing this. Perhaps it has
> something to do with my use of threading.Timer.

Yes, it does. That timer does a callback in a different thread, and you
can't reliably touch a window from a thread that didn't create the window.

Just use a wx.Timer instead, as in the attached.

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

advancephrase.py

Patrick Maher

unread,
Mar 26, 2012, 5:36:08 PM3/26/12
to wxpytho...@googlegroups.com
Thanks Tim, that was just what I needed.  I couldn't simply use the code you gave, because the time that a phrase is highlighted needs to be different for different phrases, but I was able to get my sample program to work correctly by using wx.Timer in place of threading.Timer. In case anyone is interested, my revised code is attached.

I'm wondering, though, how wx.Timer avoids the problem. Naively (that's me), one would think that the timing must take place in a different thread, in which case it isn't obvious why the problem with threading.Timer doesn't arise with wx.Timer.

Patrick


advancephrase3.py

Tim Roberts

unread,
Mar 26, 2012, 6:07:22 PM3/26/12
to wxpytho...@googlegroups.com
Patrick Maher wrote:
>
> I'm wondering, though, how wx.Timer avoids the problem. Naively
> (that's me), one would think that the timing must take place in a
> different thread, in which case it isn't obvious why the problem with
> threading.Timer doesn't arise with wx.Timer.

Your confusion is understandable. It's especially true because we
advise people to use Python-native components to solve problem whenever
they duplicate the facilities in wx, and that would seem to be the case
here.

The threading module's timer does spin off a separate thread, which
simply waits for a time and then calls the function. This short-lived
thread is thus guaranteed NOT to be the creator of any existing windows.

wx.Timer ends up calling the SetTimer API in Windows (or an equivalent
in other systems). When the interval expires, SetTimer fires off a
message to the window that owns the timer. (Actually, timer and paint
messages are a little special, but that's a different topic.) That
message gets handled by the normal message queue dispatch process, which
means that the message is handled by the thread that created the
window. THAT'S the key point.

Chris Barker

unread,
Mar 26, 2012, 7:06:40 PM3/26/12
to wxpytho...@googlegroups.com
On Mon, Mar 26, 2012 at 3:07 PM, Tim Roberts <ti...@probo.com> wrote:
> Patrick Maher wrote:
>>
>> I'm wondering, though, how wx.Timer avoids the problem. Naively
>> (that's me), one would think that the timing must take place in a
>> different thread, in which case it isn't obvious why the problem with
>> threading.Timer doesn't arise with wx.Timer.

> wx.Timer ends up calling the SetTimer API in Windows (or an equivalent


> in other systems).  When the interval expires, SetTimer fires off a
> message to the window that owns the timer.

for completeness's sake, you CAN use threading.Timer if you want, but
rather than call the wx function you want directly, you can make a
call that puts an event on the event stack -- wx.CallAfter it the
easiest way to do it. but if all you're using threads for is a timer,
it makes more sense to use wx.Timer.

-Chris


--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

Robin Dunn

unread,
Mar 26, 2012, 7:44:00 PM3/26/12
to wxpytho...@googlegroups.com

In other words, wx.Timer is based off of the native platform's APIs
meant for getting a callback/message/event after the specified amount of
time. Although at a high-level they seem to provide the same
functionality as a threading.Timer, under the covers they are very
different things.

--
Robin Dunn
Software Craftsman
http://wxPython.org

Reply all
Reply to author
Forward
0 new messages