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

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
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 (3.14 KB)

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.

advancephrase.py (3.13 KB)

···

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

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 (2.88 KB)

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.

···

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

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

···

On Mon, Mar 26, 2012 at 3:07 PM, Tim Roberts <timr@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.

--

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.Barker@noaa.gov

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.

···

On 3/26/12 3:07 PM, Tim Roberts 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.

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.

--
Robin Dunn
Software Craftsman