I have a program where I want to be able to have print statements get
written to a TextCtrl, and errors show up in another. So I made my two
TextCtrls and assigned them to sys.stdout and sys.stderr. So far so
good. However, sometimes when I print to them, I get this error:
Traceback (most recent call last):
File "C:\Python27x64\lib\site-packages\wx-2.8-msw-unicode\wx\_core.py",
line 14660, in <lambda>
lambda event: event.callable(*event.args, **event.kw) )
File "C:\mui\gui\loggingWindow.py", line 48, in stdOut
window.stdOut.write(' '.join([str(s) for s in args]))
File "C:\Python27x64\lib\site-packages\wx-2.8-msw-unicode\wx\_controls.py",
line 1990, in write
return _controls_.TextCtrl_write(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion "m_count == -1 || m_count ==
-2" failed at ..\..\src\msw\textctrl.cpp(140) in
UpdatesCountFilter::UpdatesCountFilter(): wrong initial m_updatesCount
value
I'm guessing the problem is that print statements made outside of the
main thread are causing UI updates when those should only happen in
the main thread. I tried working around it by overriding the
TextCtrl.write method:
but this results in massive error spew about NoneType not being
callable. Oddly this shows up in my stderr window just fine, but the
spew locks up the program and I can't copy&paste it.
So what's the proper way to capture stdout and stderr to a text control?
I'm guessing the problem is that print statements made outside of the
main thread are causing UI updates when those should only happen in
the main thread. I tried working around it by overriding the
TextCtrl.write method:
but this results in massive error spew about NoneType not being
callable.
Because you are passing the wx.CallAfter the return value from self.stdOut.__labWrite(*args). I expect that you wanted to use (self.stdOut.__labWrite, *args)
Oddly this shows up in my stderr window just fine, but the
spew locks up the program and I can't copy&paste it.
So what's the proper way to capture stdout and stderr to a text control?
For a slightly different approach take a look at how it is done in PyOnDemandOuputWindow, which is what is used when you pass redirect=True to wx.App.
I'm guessing the problem is that print statements made outside of the
main thread are causing UI updates when those should only happen in
the main thread. I tried working around it by overriding the
TextCtrl.write method:
but this results in massive error spew about NoneType not being
callable.
Because you are passing the wx.CallAfter the return value from
self.stdOut.__labWrite(*args). I expect that you wanted to use
(self.stdOut.__labWrite, *args)
D'oh! That's what I get for sending a help-me email late in the day
when I'm tired. Stupid mistake; thanks for the catch.
For a slightly different approach take a look at how it is done in
PyOnDemandOuputWindow, which is what is used when you pass redirect=True to
wx.App.
(Note it's PyOnDemandOutputWindow; you missed a 't'). With that term
to google, I found some other threads detailing alternate approaches.
The PyOnDemandOutputWindow doesn't quite suit my needs since it's only
created when output is first provided and I want more control over the
UI. But replacing TextCtrl.write with
wx.CallAfter(TextCtrl.AppendText) did the trick for me:
My original approach of just doing
wx.CallAfter(self.stdOut.__labWrite, *args) still resulted in that
"Count" error from time to time, but this seems to be working
flawlessly.
Thanks for the assistance!
-Chris
···
On Thu, Nov 15, 2012 at 9:53 PM, Robin Dunn <robin@alldunn.com> wrote: