Reputation: 4279
I'm trying to subclass wx.Process
such that I have a customized process launcher that fires events back to the main thread with data collected from the stdout stream. Is this a good way of doing things?
class BuildProcess(wx.Process):
def __init__(self, cmd, notify=None):
wx.Process.__init__(self, notify)
print "Constructing a build process"
self.Bind(wx.EVT_IDLE, self.on_idle)
self.Redirect()
self.cmd = cmd
self.pid = None
def start(self):
print "Starting the process"
self.pid = wx.Execute(self.cmd, wx.EXEC_ASYNC, self)
print "Started."
def on_idle(self, evt):
print "doing the idle thing..."
stream = self.GetInputStream()
if stream.CanRead():
text = stream.read()
wx.PostEvent(self, BuildEvent(EVT_BUILD_UPDATE, self, data=text))
print text
def OnTerminate(self, *args, **kwargs):
wx.Process.OnTerminate(self, *args, **kwargs)
print "Terminating"
BuildEvent
here is a custom subclass of wx.PyEvent
. The process is starting, running, and terminating correctly, but my on_idle
function is never executing, even though I'm sure I've bound it to the idle event.
Upvotes: 0
Views: 1352
Reputation: 4279
The objective is not to call methods of another process, the objective is to redirect the stdout of another process back to the parent process via "update" events fired periodically as the process executes.
One solution is to use wx.Timer to periodically poll the output stream of the process, so that we don't rely on EVT_IDLE to do the work for us (I had trouble getting EVT_IDLE to fire)
class BuildProcess(wx.Process):
def __init__(self, cmd, notify=None):
wx.Process.__init__(self, notify)
self.Redirect()
self.cmd = cmd
self.pid = None
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.on_timer)
def start(self):
wx.PostEvent(self, BuildEvent(EVT_BUILD_STARTED, self))
self.pid = wx.Execute(self.cmd, wx.EXEC_ASYNC, self)
self.timer.Start(100)
def on_timer(self, evt):
stream = self.GetInputStream()
if stream.CanRead():
text = stream.read()
wx.PostEvent(self, BuildEvent(EVT_BUILD_UPDATE, self, data=text))
def OnTerminate(self, *args, **kwargs):
print "terminating..."
stream = self.GetInputStream()
if stream.CanRead():
text = stream.read()
wx.PostEvent(self, BuildEvent(EVT_BUILD_UPDATE, self, data=text))
if self.timer:
self.timer.Stop()
wx.PostEvent(self, BuildEvent(EVT_BUILD_FINISHED, self))
By this method, every 100ms the output stream is read, packaged up, and shipped off as a build event.
Upvotes: 1
Reputation: 41813
From looking the the wxProcess docs, I don't think it works that way: wxProcess will create a new, seperate process running as a child of you current process. It is not possible to run methods connected to a message in such a process.
Maybe you can connect your idle event to a function or method in you main thread.
Or, mayby the wxThread class is what you really want to use.
Upvotes: 0