Python multiprocessing redirect stdout of a child process to a Tkinter Text -
i'm trying use tkinter gui launch child process , display stdout/stderr output text widget. initially, thought sys.stdout can redirected text widget setting "sys.stdout = text_widget" seems not. comes error: "text instance has no attribute 'flush'".
i checked online , got solutions, using queue communicate child process. however, none of them fit case because of special requirement:
- the child process should better launched "multiprocessing.process" because easier use shared variables, makes subprocess solutions usable.
- the codes of child process there quite lot "print" inside, don't want modify them "queue.put()" or else.
in case, come solution of getting "multiprocessing.process"'s "print" output , display tkinter text? many thanks!
an example code of case follows:
import sys import time multiprocessing import process tkinter import * def test_child(): print 'child running' def test_parent(): print 'parent running' time.sleep(0.5) process(target=test_child).start() def set_txt(msg): gui_txt.insert(end, str(msg)) gui_txt.see(end) if __name__ == '__main__': gui_root = tk() gui_txt = text(gui_root) gui_txt.pack() gui_btn = button(gui_root, text='test', command=test_parent) gui_btn.pack() gui_txt.write = set_txt sys.stdout = gui_txt gui_root.mainloop()
it still possible use queues without having rid of of print
statements. can use process
dependent stdout
redirect this. solution below uses queue
subclass mimic stdout
. queue monitored thread looks new text gets pumped text widget.
import sys import time multiprocessing import process multiprocessing.queues import queue threading import thread tkinter import * # function takes text widget , queue inputs. # functions waiting on new data entering queue, when # finds new data insert text widget def text_catcher(text_widget,queue): while true: text_widget.insert(end, queue.get()) # queue behaves stdout class stdoutqueue(queue): def __init__(self,*args,**kwargs): queue.__init__(self,*args,**kwargs) def write(self,msg): self.put(msg) def flush(self): sys.__stdout__.flush() def test_child(q): # line redirects stdout inside current process sys.stdout = q # or sys.stdout = sys.__stdout__ if want print child terminal print 'child running' def test_parent(q): # again redirects inside current (main) process # commenting out cause child write widget sys.stdout = q print 'parent running' time.sleep(0.5) process(target=test_child,args=(q,)).start() if __name__ == '__main__': gui_root = tk() gui_txt = text(gui_root) gui_txt.pack() q = stdoutqueue() gui_btn = button(gui_root, text='test', command=lambda:test_parent(q),) gui_btn.pack() # instantiate , start text monitor monitor = thread(target=text_catcher,args=(gui_txt,q)) monitor.daemon = true monitor.start() gui_root.mainloop()
Comments
Post a Comment