I have this problem. I’m creating an editor and I need console output(sys.stderr and sys.stdout) outputted to a textview. The problem is that when I start the console, it waits for it to quit, but I want it to catch anything and output it to the textview, so I thought that you might need different threads, but does it not then make it impossible to catch anything from the other thread? I want this in case the editor was not started from a terminal. It will be used as a module if you are wondering. This is the code so far:
import sys
import gtk
import pygtk
pygtk.require('2.0')
class Console:
def __init__(self):
tv = gtk.TextView()
tv.set_editable(False)
tv.set_wrap_mode(gtk.WRAP_WORD)
self.buffer = tv.get_buffer()
table = gtk.Table(3, 6, gtk.FALSE)
table.attach(tv, 0, 6, 0, 1)
#### Main window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect('destroy_event', lambda w, e: gtk.mainquit())
self.window.connect('delete_event', lambda w, e: gtk.mainquit())
self.window.set_border_width(10)
self.window.add(table)
self.window.set_title('Search')
self.window.set_default_size(300, 300)
self.window.show_all()
def main(self):
gtk.main()
c = Console()
class ConsoleOutput:
def __init__(self, source):
self.source=source
self.buf = []
def write(self, data):
self.buf.append(data)
if data.endswith('\n'):
c.buffer.insert(c.buffer.get_end_iter(), ''.join(self.buf))
self.buf = []
def __del__(self):
if self.buf != []:
c.buffer.insert(c.buffer.get_end_iter(), ''.join(self.buf))
Thank you.
Since you want to catch
sys.stdoutandsys.stderrand these are global to the interpreter according to the documentation, you should be able to catch them regardless of the thread where the output was done.On the other hand, your code wasn’t very far from working. It was missing a call to the event loop, which is why it freezed. I added a call to
c.main().I also added a button which prints “hello” and I replaced the default
sys.stdoutby an instance ofConsoleOutput, so “hello” should appear on the textview.Edit: I’ve updated my answer to include an example of threads. Two threads are created when pressing the button. I used python’s threading module. I think pygtk has its own threading facilities, it’s just that python’s module came up first when searching Google.
The important point to be made is in the
ConsoleOutputclass. Note that I have wrapped the code that updates the console buffer in a method calledself.update_buffer, which is called indirectly throughgobject.idle_add. What this function does is to callself.update_bufferwithin the gtk event loop. It must be done this way because all calls that update the GUI must be done within the event loop, otherwise Gtk can’t synchronize access to its data structures and you may get strange behaviours and crashes.There may be some buffering issues that prevent the output from appearing at once in the textview.