Поскольку вы хотите перехватить sys.stdout
и sys.stderr
, и они являются глобальными для интерпретатора в соответствии с документацией, вы должны быть в состоянии перехватить их независимо от потока, в котором был сделан вывод.
С другой стороны, ваш код не очень далек от работы. Отсутствовал вызов в цикле событий, поэтому он завис. Я добавил звонок на c.main()
.
Я также добавил кнопку, которая печатает «привет», и заменил значение по умолчанию sys.stdout
на экземпляр ConsoleOutput
, поэтому «приветствие» должно появиться в текстовом представлении.
import sys
import gtk
import pygtk
pygtk.require('2.0')
import gobject
import threading
class MyThread(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
for i in range(10):
print "Hello %d from thread %s" % (i, self.name)
class Console:
def __init__(self):
tv = gtk.TextView()
tv.set_editable(False)
tv.set_wrap_mode(gtk.WRAP_WORD)
self.buffer = tv.get_buffer()
button = gtk.Button("Update")
button.connect("clicked", self.update, None)
table = gtk.Table(3, 6, gtk.FALSE)
table.attach(tv, 0, 6, 0, 1)
table.attach(button, 0, 6, 1, 2)
#### 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 update(self, widget, data=None):
print "hello"
MyThread("A").start()
MyThread("B").start()
def main(self):
gtk.main()
c = Console()
class ConsoleOutput:
def __init__(self, source):
self.source=source
self.buf = []
def update_buffer(self):
c.buffer.insert(c.buffer.get_end_iter(), ''.join(self.buf))
self.buf = []
def write(self, data):
self.buf.append(data)
if data.endswith('\n'):
gobject.idle_add(self.update_buffer)
def __del__(self):
if self.buf != []:
gobject.idle_add(self.update_buffer)
sys.stdout = ConsoleOutput(None)
c.main()
Изменить: я обновил свой ответ, чтобы включить пример темы. При нажатии на кнопку создаются две темы. Я использовал модуль потоков Python. Я думаю, что у pygtk есть свои средства для работы с потоками, просто модуль python появился первым при поиске в Google.
Важный момент, который необходимо сделать, относится к классу ConsoleOutput
. Обратите внимание, что я обернул код, который обновляет буфер консоли, в метод с именем self.update_buffer
, который вызывается косвенно через gobject.idle_add
. Эта функция вызывает self.update_buffer
в цикле событий gtk . Это должно быть сделано так, потому что все вызовы, которые обновляют GUI, должны выполняться в цикле событий , в противном случае Gtk не может синхронизировать доступ к своим структурам данных, и вы можете получить странное поведение и сбои.
Могут быть некоторые проблемы с буферизацией, которые не позволяют выводу сразу появиться в текстовом представлении.