author | lbessard |
Mon, 23 Mar 2009 16:26:13 +0100 | |
changeset 323 | 9f07f0d429df |
parent 235 | a66e150f2888 |
child 361 | 331d698e1118 |
permissions | -rw-r--r-- |
#!/usr/bin/env python # -*- coding: utf-8 -*- #This file is part of Beremiz, a Integrated Development Environment for #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. # #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD # #See COPYING file for copyrights details. # #This library is free software; you can redistribute it and/or #modify it under the terms of the GNU General Public #License as published by the Free Software Foundation; either #version 2.1 of the License, or (at your option) any later version. # #This library is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #General Public License for more details. # #You should have received a copy of the GNU General Public #License along with this library; if not, write to the Free Software #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import time import wx import subprocess, ctypes import threading import os if os.name == 'posix': from signal import SIGTERM, SIGKILL class outputThread(threading.Thread): """ Thread is used to print the output of a command to the stdout """ def __init__(self, Proc, fd, callback=None, endcallback=None): threading.Thread.__init__(self) self.killed = False self.finished = False self.retval = None self.Proc = Proc self.callback = callback self.endcallback = endcallback self.fd = fd def run(self): outchunk = None self.retval = None while outchunk != '' and not self.killed : outchunk = self.fd.readline() if self.callback : self.callback(outchunk) while self.retval is None and not self.killed : self.retval = self.Proc.poll() outchunk = self.fd.readline() if self.callback : self.callback(outchunk) while outchunk != '' and not self.killed : outchunk = self.fd.readline() if self.endcallback: try: err = self.Proc.wait() except: err = self.retval self.finished = True wx.CallAfter(self.endcallback, self.Proc.pid, err) class ProcessLogger: def __init__(self, logger, Command, finish_callback=None, no_stdout=False, no_stderr=False, no_gui=True): self.logger = logger self.Command_str = Command self.Command = [] for i,word in enumerate(Command.replace("'",'"').split('"')): if i % 2 == 0: word = word.strip() if len(word) > 0: self.Command.extend(word.split()) else: self.Command.append(word) self.finish_callback = finish_callback self.no_stdout = no_stdout self.no_stderr = no_stderr self.startupinfo = None self.errlen = 0 self.outlen = 0 self.exitcode = None self.outdata = "" self.errdata = "" self.finished = False popenargs= { "cwd":os.getcwd(), "stdin":subprocess.PIPE, "stdout":subprocess.PIPE, "stderr":subprocess.PIPE} if no_gui == True and wx.Platform == '__WXMSW__': self.startupinfo = subprocess.STARTUPINFO() self.startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW popenargs["startupinfo"] = self.startupinfo elif wx.Platform == '__WXGTK__': popenargs["shell"] = False #True self.Proc = subprocess.Popen( self.Command, **popenargs ) self.outt = outputThread( self.Proc, self.Proc.stdout, self.output, self.finish) self.outt.start() self.errt = outputThread( self.Proc, self.Proc.stderr, self.errors) self.errt.start() def output(self,v): self.outdata += v self.outlen += 1 if not self.no_stdout: wx.CallAfter(self.logger.write,v) def errors(self,v): self.errdata += v self.errlen += 1 if not self.no_stderr: wx.CallAfter(self.logger.write_warning,v) def log_the_end(self,ecode,pid): self.logger.write(self.Command_str + "\n") self.logger.write_warning("exited with status %s (pid %s)\n"%(str(ecode),str(pid))) def finish(self, pid,ecode): self.finished = True self.exitcode = ecode if self.exitcode != 0: wx.CallAfter(self.log_the_end,ecode,pid) if self.finish_callback is not None: self.finish_callback(self,ecode,pid) def kill(self,gently=True): self.outt.killed = True self.errt.killed = True if wx.Platform == '__WXMSW__': PROCESS_TERMINATE = 1 handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.Proc.pid) ctypes.windll.kernel32.TerminateProcess(handle, -1) ctypes.windll.kernel32.CloseHandle(handle) else: if gently: sig=SIGTERM else: sig=SIGKILL try: os.kill(self.Proc.pid, sig) except: pass self.outt.join() self.errt.join() def spin(self, timeout=None, out_limit=None, err_limit=None, keyword = None, kill_it = True): count = 0 while not self.finished: if err_limit and self.errlen > err_limit: break if out_limit and self.outlen > out_limit: break if timeout: if count > timeout: break count += 1 if keyword and self.outdata.find(keyword)!=-1: break wx.Yield() time.sleep(0.01) if not self.outt.finished and kill_it: self.kill() return [self.exitcode, self.outdata, self.errdata]