Package Gnumed :: Package pycommon :: Module gmWorkerThread
[frames] | no frames]

Source Code for Module Gnumed.pycommon.gmWorkerThread

  1  __doc__ = """GNUmed worker threads.""" 
  2  #===================================================================== 
  3  __author__ = "K.Hilbert <karsten.hilbert@gmx.net>" 
  4  __license__ = "GPL v2 or later" 
  5   
  6  import sys 
  7  import logging 
  8  import threading 
  9  import datetime as dt 
 10  import pickle 
 11  import copy 
 12   
 13  # wx.CallAfter() does not seem to work with multiprocessing ! 
 14  #import multiprocessing 
 15   
 16   
 17  if __name__ == '__main__': 
 18          sys.path.insert(0, '../../') 
 19   
 20   
 21  _log = logging.getLogger('gm.worker') 
 22   
 23  #===================================================================== 
24 -def execute_in_worker_thread(payload_function=None, payload_kwargs=None, completion_callback=None, worker_name=None):
25 """Create a thread and have it execute <payload_function>. 26 27 <completion_callback> - if not None - better be prepared to 28 receive the result of <payload_function>. 29 """ 30 assert (callable(payload_function)), 'payload function <%s> is not callable' % payload_function 31 assert ((completion_callback is None) or callable(completion_callback)), 'completion callback <%s> is not callable' % completion_callback 32 33 _log.debug('worker [%s]', worker_name) 34 # try to decouple from calling thread 35 try: 36 __payload_kwargs = copy.deepcopy(payload_kwargs) 37 except (copy.error, pickle.PickleError): 38 _log.exeption('failed to copy.deepcopy(payload_kwargs): %s', payload_kwargs) 39 _log.error('using shallow copy and hoping for the best') 40 __payload_kwargs = copy.copy(payload_kwargs) 41 worker_thread = None 42 43 #------------------------------- 44 def _run_payload(): 45 try: 46 if payload_kwargs is None: 47 payload_result = payload_function() 48 else: 49 payload_result = payload_function(**__payload_kwargs) 50 _log.debug('finished running payload function: %s', payload_function) 51 except Exception: 52 _log.exception('error running payload function: %s', payload_function) 53 return 54 55 if completion_callback is None: 56 return 57 58 try: 59 completion_callback(payload_result) 60 _log.debug('finished running completion callback') 61 except Exception: 62 _log.exception('error running completion callback: %s', completion_callback) 63 _log.info('worker thread [name=%s, PID=%s] shuts down', worker_thread.name, worker_thread.ident) 64 return
65 #------------------------------- 66 67 if worker_name is None: 68 __thread_name = dt.datetime.now().strftime('%f-%S') 69 else: 70 __thread_name = '%sThread-%s' % ( 71 worker_name, 72 dt.datetime.now().strftime('%f') 73 ) 74 _log.debug('creating thread "%s"', __thread_name) 75 _log.debug(' "%s" payload function: %s', __thread_name, payload_function) 76 _log.debug(' "%s" results callback: %s', __thread_name, completion_callback) 77 #worker_thread = multiprocessing.Process ( 78 worker_thread = threading.Thread ( 79 target = _run_payload, 80 name = __thread_name 81 ) 82 # we don't want hung workers to prevent us from exiting GNUmed 83 worker_thread.daemon = True 84 _log.info('starting thread "%s"', __thread_name) 85 worker_thread.start() 86 _log.debug(' "%s" ident (= PID): %s', worker_thread.name, worker_thread.ident) 87 # from here on, another thread executes _run_payload() 88 # which executes payload_function() and, eventually, 89 # completion_callback() if available, 90 # return thread ident so people can join() it if needed 91 return worker_thread.ident 92 93 #===================================================================== 94 # main 95 #===================================================================== 96 if __name__ == "__main__": 97 98 if len(sys.argv) < 2: 99 sys.exit() 100 101 if sys.argv[1] != 'test': 102 sys.exit() 103 104 import time 105 import random 106 107 from Gnumed.pycommon import gmLog2 108
109 - def test_print_dots(ident=None):
110 111 def slowly_print_dots(info=None): 112 for i in range(5): 113 print('* (#%s in %s)' % (i, info)) 114 time.sleep(1 + (random.random()*4)) 115 return '%s' % time.localtime()
116 117 def print_dot_end_time(time_str): 118 print('done: %s' % time_str) 119 120 execute_in_worker_thread ( 121 payload_function = slowly_print_dots, 122 payload_kwargs = {'info': ident}, 123 completion_callback = print_dot_end_time 124 ) 125 126 test_print_dots('A') 127 test_print_dots('B') 128