Segmentation fault while redirecting sys.stdout to Tkinter.Text widget

2024/10/2 22:16:05

I'm in the process of building a GUI-based application with Python/Tkinter that builds on top of the existing Python bdb module. In this application, I want to silence all stdout/stderr from the console and redirect it to my GUI. To accomplish this purpose, I've written a specialized Tkinter.Text object (code at the end of the post).

The basic idea is that when something is written to sys.stdout, it shows up as a line in the "Text" with the color black. If something is written to sys.stderr, it shows up as a line in the "Text" with the color red. As soon as something is written, the Text always scrolls down to view the most recent line.

I'm using Python 2.6.1 at the moment. On Mac OS X 10.5, this seems to work great. I have had zero problems with it. On RedHat Enterprise Linux 5, however, I pretty reliably get a segmentation fault during the run of a script. The segmentation fault doesn't always occur in the same place, but it pretty much always occurs. If I comment out the sys.stdout= and sys.stderr= lines from my code, the segmentation faults seem to go away.

I'm sure there are other ways around this that I will probably have to resort to, but can anyone see anything I'm doing blatantly wrong here that could be causing these segmentation faults? It's driving me nuts. Thanks!

PS - I realize redirecting sys.stderr to the GUI might not be a great idea, but I still get segmentation faults even when I only redirect sys.stdout and not sys.stderr. I also realize that I'm allowing the Text to grow indefinitely at the moment.

class ConsoleText(tk.Text):'''A Tkinter Text widget that provides a scrolling display of consolestderr and stdout.'''class IORedirector(object):'''A general class for redirecting I/O to this Text widget.'''def __init__(self,text_area):self.text_area = text_areaclass StdoutRedirector(IORedirector):'''A class for redirecting stdout to this Text widget.'''def write(self,str):self.text_area.write(str,False)class StderrRedirector(IORedirector):'''A class for redirecting stderr to this Text widget.'''def write(self,str):self.text_area.write(str,True)def __init__(self, master=None, cnf={}, **kw):'''See the __init__ for Tkinter.Text for most of this stuff.'''tk.Text.__init__(self, master, cnf, **kw)self.started = Falseself.write_lock = threading.Lock()self.tag_configure('STDOUT',background='white',foreground='black')self.tag_configure('STDERR',background='white',foreground='red')self.config(state=tk.DISABLED)def start(self):if self.started:returnself.started = Trueself.original_stdout = sys.stdoutself.original_stderr = sys.stderrstdout_redirector = ConsoleText.StdoutRedirector(self)stderr_redirector = ConsoleText.StderrRedirector(self)sys.stdout = stdout_redirectorsys.stderr = stderr_redirectordef stop(self):if not self.started:returnself.started = Falsesys.stdout = self.original_stdoutsys.stderr = self.original_stderrdef write(self,val,is_stderr=False):#Fun Fact:  The way Tkinter Text objects work is that if they're disabled,#you can't write into them AT ALL (via the GUI or programatically).  Since we want them#disabled for the user, we have to set them to NORMAL (a.k.a. ENABLED), write to them,#then set their state back to DISABLED.self.write_lock.acquire()self.config(state=tk.NORMAL)self.insert('end',val,'STDERR' if is_stderr else 'STDOUT')self.see('end')self.config(state=tk.DISABLED)self.write_lock.release()
Answer

I'm assuming this is part of a larger, threaded program.

Instead of using a lock, have your code write to a thread-safe queue object. Then, in your main thread you poll the queue and write to the text widget. You can do the polling using the event loop (versus writing your own loop) by running the polling job which reschedules itself to run a few ms later using after (a couple hundred ms is probably quite sufficient).

https://en.xdnf.cn/q/70795.html

Related Q&A

Why do pandas and dask perform better when importing from CSV compared to HDF5?

I am working with a system that currently operates with large (>5GB) .csv files. To increase performance, I am testing (A) different methods to create dataframes from disk (pandas VS dask) as well a…

is there any pool for ThreadingMixIn and ForkingMixIn for SocketServer?

I was trying to make an http proxy using BaseHttpServer which is based on SocketServer which got 2 asynchronous Mixins (ThreadingMixIn and ForkingMixIn)the problem with those two that they work on each…

Python - Read data from netCDF file with time as seconds since beginning of measurement

I need to extract values from a netCDf file. I am pretty new to python and even newer this file format. I need to extract time series data at a specific location (lat, lon). I have found that there is …

PyQt Multiline Text Input Box

I am working with PyQt and am attempting to build a multiline text input box for users. However, when I run the code below, I get a box that only allows for a single line of text to be entered. How to …

Calculate the sum of model properties in Django

I have a model Order which has a property that calculates an order_total based on OrderItems linked by foreign key.I would like to calculate the sum of a number of Order instances order_total propertie…

Set Host-header when using Python and urllib2

Im using my own resolver and would like to use urllib2 to just connect to the IP (no resolving in urllib2) and I would like set the HTTP Host-header myself. But urllib2 is just ignoring my Host-header:…

Full-featured date and time library

Im wondering if anyone knows of a good date and time library that has correctly-implemented features like the following:Microsecond resolution Daylight savings Example: it knows that 2:30am did not exi…

Mean of a correlation matrix - pandas data fram

I have a large correlation matrix in a pandas python DataFrame: df (342, 342).How do I take the mean, sd, etc. of all of the numbers in the upper triangle not including the 1s along the diagonal?Thank…

How to set imshow scale

Im fed up with matplotlib in that its so hard to plot images in specified size.Ive two images in 32*32, 20*20 sizes. I just want to plot them in its original size, or in proportion to its original size…

Python distutils gcc path

Im trying to cross-compile the pycrypto package, and Im getting closer and closer however, Ive hit an issue I just cant figure out.I want distutils to use the cross-compile specific gcc- so I set the C…