WxPython: execute command asynchronously, display stdout in text widget
I'm looking for a wxPython equivalent for my answer for Tcl / Tk examples? ... In particular, I want to see an example of creating multiple buttons, each of which runs some external command when pressed. While the process is running, I want the wxPython scrollable widget to be output.
While the process is running, the GUI should not be blocked. Suppose, for example, that one of the buttons can initiate a development task, such as creating or running unit tests.
a source to share
Here's a complete working example.
import wx
import functools
import threading
import subprocess
import time
class Frame(wx.Frame):
def __init__(self):
super(Frame, self).__init__(None, -1, 'Threading Example')
# add some buttons and a text control
panel = wx.Panel(self, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
for i in range(3):
name = 'Button %d' % (i+1)
button = wx.Button(panel, -1, name)
func = functools.partial(self.on_button, button=name)
button.Bind(wx.EVT_BUTTON, func)
sizer.Add(button, 0, wx.ALL, 5)
text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY)
self.text = text
sizer.Add(text, 1, wx.EXPAND|wx.ALL, 5)
panel.SetSizer(sizer)
def on_button(self, event, button):
# create a new thread when a button is pressed
thread = threading.Thread(target=self.run, args=(button,))
thread.setDaemon(True)
thread.start()
def on_text(self, text):
self.text.AppendText(text)
def run(self, button):
cmd = ['ls', '-lta']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in proc.stdout:
wx.CallAfter(self.on_text, line)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = Frame()
frame.Show()
app.MainLoop()
a source to share
Start stream on button click:
try:
r = threading.Thread(target=self.mycallback)
r.setDaemon(1)
r.start()
except:
print "Error starting thread"
return False
Use wx.PostEvent and wx.lib.newevent to send messages from callbacks to the main thread.
This link might be helpful.
a source to share
Brian, try something like this:
import subprocess, sys
def doit(cmd):
#print cmd
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).stdout
return out.read()
So, when the button is clicked, the command is run using the subprocess module and you get the output as a string. You can assign it to a text control value to show it. You may need to out.readfully () or read it several times to show the text gradually.
If the button and text box are not familiar, then a quick look at the wxPython demo will show you exactly what to do.
a source to share