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
14
15
16
17 if __name__ == '__main__':
18 sys.path.insert(0, '../../')
19
20
21 _log = logging.getLogger('gm.worker')
22
23
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
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
78 worker_thread = threading.Thread (
79 target = _run_payload,
80 name = __thread_name
81 )
82
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
88
89
90
91 return worker_thread.ident
92
93
94
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
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