secret
Last active

  • Download Gist
show-subprocess-output-io-watch.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#!/usr/bin/python
from subprocess import Popen, PIPE
 
from gi.repository import GObject, Gtk
 
# create GUI to show subprocess output
win = Gtk.Window()
win.set_default_size(640, 480)
label = Gtk.Label('process output')
win.add(label)
 
# start dummy subprocess to generate some output
proc = Popen(["python", "-u", "-c", """import itertools, sys, time
for i in itertools.count():
print(i)
sys.stderr.write(".") # show that we are alive in terminal
time.sleep(0.5)
"""], stdout=PIPE)
 
# read from subprocess
def read_data(source, condition):
line = source.readline() # might block
if not line:
source.close()
return False # stop reading
# update text
label.set_text('Subprocess output: %r' % (line.strip(),))
return True # continue reading
io_id = GObject.io_add_watch(proc.stdout, GObject.IO_IN, read_data)
 
# exit subprocess if GUI is closed
def quit(win, event, proc):
GObject.source_remove(io_id) # stop watching
proc.terminate()
 
# kill subprocess if it hasn't exited in timeout seconds
timeout = 5
def poll(proc, countdown):
if proc.poll() is None: # subprocess hasn't exited yet
countdown[0] -= 1
if countdown[0] <= 0:
proc.kill()
proc.wait()
Gtk.main_quit()
else:
return True # continue polling
else: # subprocess exited
Gtk.main_quit()
# call poll() once a second
GObject.timeout_add(1000, poll, proc, [timeout])
 
win.connect('delete-event', quit, proc)
 
win.show_all()
Gtk.main()
show-subprocess-output-thread.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
#!/usr/bin/python
from contextlib import closing
from threading import Thread
from subprocess import Popen, PIPE
 
from gi.repository import GObject, Gtk
GObject.threads_init() # all Gtk is in the main thread;
# only GObject.idle_add() is in the background thread
 
# create GUI to show subprocess output
win = Gtk.Window()
win.set_default_size(640, 480)
label = Gtk.Label('process output')
win.add(label)
 
# start dummy subprocess to generate some output
proc = Popen(["python", "-u", "-c", """import itertools, sys, time
for i in itertools.count():
print(i)
sys.stderr.write(".") # show that we are alive in terminal
time.sleep(0.5)
"""], stdout=PIPE)
 
# read from subprocess in a separate thread
def reader_thread(proc, update_text):
with closing(proc.stdout) as file:
for line in iter(file.readline, b''):
# execute update_text() in GUI thread
GObject.idle_add(update_text, 'Subprocess output: %r' % (
line.strip(),))
 
t = Thread(target=reader_thread, args=[proc, label.set_text])
t.daemon = True # exit with the program
t.start()
 
# exit subprocess if GUI is closed
def quit(win, event, proc):
proc.terminate()
 
# kill subprocess if it hasn't exited in timeout seconds
timeout = 5
def poll(proc, countdown):
if proc.poll() is None: # subprocess hasn't exited yet
countdown[0] -= 1
if countdown[0] <= 0:
proc.kill()
proc.wait()
Gtk.main_quit()
else:
return True # continue polling
else: # subprocess exited
Gtk.main_quit()
# call poll() once a second
GObject.timeout_add(1000, poll, proc, [timeout])
 
win.connect('delete-event', quit, proc)
 
win.show_all()
Gtk.main()

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.