# HG changeset patch # User Edouard Tisserant # Date 1351070351 -7200 # Node ID 06495975e8a4034af9dbfdb50ef288150fe9e316 # Parent ee6adf7586c167c36316a4b812a7625317228999 Added caching for python eval (avoid compiling when same code called, but still execute). Cleaned up some evaluator related code. diff -r ee6adf7586c1 -r 06495975e8a4 Beremiz_service.py --- a/Beremiz_service.py Tue Oct 23 11:34:37 2012 +0200 +++ b/Beremiz_service.py Wed Oct 24 11:19:11 2012 +0200 @@ -434,8 +434,12 @@ if not os.path.isdir(WorkingDir): os.mkdir(WorkingDir) -def default_evaluator(callable, *args, **kwargs): - return callable(*args,**kwargs) +def default_evaluator(tocall, *args, **kwargs): + try: + res=(tocall(*args,**kwargs), None) + except Exception,exp: + res=(None, exp) + return res class Server(): def __init__(self, servicename, ip_addr, port, workdir, argv, autostart=False, statuschange=None, evaluator=default_evaluator, website=None): @@ -681,29 +685,26 @@ if havewx: from threading import Semaphore wx_eval_lock = Semaphore(0) - mythread = currentThread() + main_thread = currentThread() def statuschange(status): wx.CallAfter(taskbar_instance.UpdateIcon,status) - eval_res = None - def wx_evaluator(callable, *args, **kwargs): - global eval_res - try: - eval_res=callable(*args,**kwargs) - except Exception,e: - PLCprint("#EXCEPTION : "+str(e)) - finally: - wx_eval_lock.release() - - def evaluator(callable, *args, **kwargs): - # call directly the callable function if call from the wx mainloop (avoid dead lock) - if(mythread == currentThread()): - callable(*args,**kwargs) + def wx_evaluator(obj, *args, **kwargs): + tocall,args,kwargs = obj.call + obj.res = default_evaluator(tocall, *args, **kwargs) + wx_eval_lock.release() + + def evaluator(tocall, *args, **kwargs): + global main_thread + if(main_thread == currentThread()): + # avoid dead lock if called from the wx mainloop + return default_evaluator(tocall, *args, **kwargs) else: - wx.CallAfter(wx_evaluator,callable,*args,**kwargs) + o=type('',(object,),dict(call=(tocall, args, kwargs), res=None)) + wx.CallAfter(wx_evaluator,o) wx_eval_lock.acquire() - return eval_res + return o.res pyroserver = Server(servicename, given_ip, port, WorkingDir, argv, autostart, statuschange, evaluator, website) taskbar_instance = BeremizTaskBarIcon(pyroserver, enablewx) diff -r ee6adf7586c1 -r 06495975e8a4 runtime/PLCObject.py --- a/runtime/PLCObject.py Tue Oct 23 11:34:37 2012 +0200 +++ b/runtime/PLCObject.py Wed Oct 24 11:19:11 2012 +0200 @@ -222,18 +222,32 @@ self.StartSem.release() self.evaluator(self.PrepareRuntimePy) res,cmd,blkid = "None","None",ctypes.c_void_p() + compile_cache={} while True: # print "_PythonIterator(", res, ")", cmd = self._PythonIterator(res,blkid) + FBID = blkid.value # print " -> ", cmd, blkid if cmd is None: break try : - self.python_threads_vars["FBID"]=blkid.value - res = str(self.evaluator(eval,cmd,self.python_threads_vars)) + self.python_threads_vars["FBID"]=FBID + ccmd,AST =compile_cache.get(FBID, (None,None)) + if ccmd is None or ccmd!=cmd: + AST = compile(cmd, '', 'eval') + compile_cache[FBID]=(cmd,AST) + result,exp = self.evaluator(eval,cmd,self.python_threads_vars) + if exp is not None: + raise(exp) + else: + res=str(result) + self.python_threads_vars["FBID"]=None except Exception,e: res = "#EXCEPTION : "+str(e) - PLCprint(res) + PLCprint(('*** Python eval EXCEPTION ***\n'+ + '| Function Block ID: %d\n'+ + '| Command : "%s"\n'+ + '| Exception : "%s"')%(FBID,cmd,str(e))) self.PLCStatus = "Stopped" self.StatusChange() self.evaluator(self.FinishRuntimePy)