h2lib 13.0.707__cp38-cp38-win_amd64.whl → 13.1.1__cp38-cp38-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- h2lib/HAWC2Lib.dll +0 -0
- h2lib/_version.py +3 -3
- {h2lib-13.0.707.dist-info → h2lib-13.1.1.dist-info}/METADATA +3 -2
- h2lib-13.1.1.dist-info/RECORD +10 -0
- {h2lib-13.0.707.dist-info → h2lib-13.1.1.dist-info}/WHEEL +1 -1
- h2lib-13.1.1.dist-info/top_level.txt +1 -0
- h2lib-13.0.707.dist-info/RECORD +0 -14
- h2lib-13.0.707.dist-info/top_level.txt +0 -2
- multiclass_interface/mpi_interface.py +0 -184
- multiclass_interface/multi_object_list.py +0 -57
- multiclass_interface/multiprocess_interface.py +0 -193
- multiclass_interface/my_test_cls.py +0 -33
h2lib/HAWC2Lib.dll
CHANGED
Binary file
|
h2lib/_version.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
# This file is autogenerated and should not be modified manually
|
2
|
-
__version__ = '13.
|
3
|
-
h2lib_version = '13.
|
4
|
-
hawc2_version = '13.0
|
2
|
+
__version__ = '13.1.1'
|
3
|
+
h2lib_version = '13.1.1'
|
4
|
+
hawc2_version = '13.1.0+1-g7269dc1'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: h2lib
|
3
|
-
Version: 13.
|
4
|
-
Summary: Python interface to HAWC2 (13.0
|
3
|
+
Version: 13.1.1
|
4
|
+
Summary: Python interface to HAWC2 (13.1.0+1-g7269dc1)
|
5
5
|
Download-URL:
|
6
6
|
Author: Mads M. Pedersen, S.G.Horcas and N.G.Ramos
|
7
7
|
Author-email: mmpe@dtu.dk
|
@@ -13,6 +13,7 @@ Project-URL: Tracker, https://gitlab.windenergy.dtu.dk/HAWC2/HAWC2Lib/-/issues
|
|
13
13
|
Requires-Dist: numpy
|
14
14
|
Requires-Dist: intel-fortran-rt ==2021.3.0
|
15
15
|
Requires-Dist: mkl ==2021.3.0
|
16
|
+
Requires-Dist: multiclass-interface
|
16
17
|
Provides-Extra: test
|
17
18
|
Requires-Dist: h2lib-tests ; extra == 'test'
|
18
19
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
h2lib/HAWC2Lib.dll,sha256=YLhwTrJ7xZrpDRbroMi-xx-7GegRMa0GF02wtWH_w9I,29719552
|
2
|
+
h2lib/__init__.py,sha256=f3fO4I6IEFRM9LaV2O3w9Pioj3GPI8qRl7P5Tg5ONtE,528
|
3
|
+
h2lib/_h2lib.py,sha256=PvXyuoVW6IDbjeYWYtCHRYcpLMlZh7aCiJkfLBl88gg,14938
|
4
|
+
h2lib/_version.py,sha256=meE3BFlhYd9SkEy2QSnHjr3_ZXS6vYZ1wL07UGZdC0E,153
|
5
|
+
h2lib/dll_wrapper.py,sha256=vO7IGbnPTpzrbjsvm-jRnYabXM97gCukJDTPJHDLEpA,11824
|
6
|
+
h2lib/h2lib_signatures.py,sha256=uIcqvgVbm_L5C4jpHc9mBqz_6G5sLIk_6n2i-j1oA04,14500
|
7
|
+
h2lib-13.1.1.dist-info/METADATA,sha256=9MLhbLu0rHyw_8ceorxGElyh53ZUphxFhg-GtOB6ROU,669
|
8
|
+
h2lib-13.1.1.dist-info/WHEEL,sha256=Wb4yjwIXVKEpht4JWFUZNCzpG7JLBNZnqtK2YNdqLkI,100
|
9
|
+
h2lib-13.1.1.dist-info/top_level.txt,sha256=y_a-tUqphEZQ_0nsWSMaSb21P8Lsd8hUxUdE9g2Dcbk,6
|
10
|
+
h2lib-13.1.1.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
h2lib
|
h2lib-13.0.707.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
h2lib/HAWC2Lib.dll,sha256=ZazvaRRCDiES0BaTcf6nB5akjZ1_dtjhlQyHE906_qE,29301760
|
2
|
-
h2lib/__init__.py,sha256=f3fO4I6IEFRM9LaV2O3w9Pioj3GPI8qRl7P5Tg5ONtE,528
|
3
|
-
h2lib/_h2lib.py,sha256=PvXyuoVW6IDbjeYWYtCHRYcpLMlZh7aCiJkfLBl88gg,14938
|
4
|
-
h2lib/_version.py,sha256=DTOnJ6TejF5GJdfnnNFQacsquZHuaLQ3ESheiuYsWeI,146
|
5
|
-
h2lib/dll_wrapper.py,sha256=vO7IGbnPTpzrbjsvm-jRnYabXM97gCukJDTPJHDLEpA,11824
|
6
|
-
h2lib/h2lib_signatures.py,sha256=uIcqvgVbm_L5C4jpHc9mBqz_6G5sLIk_6n2i-j1oA04,14500
|
7
|
-
multiclass_interface/mpi_interface.py,sha256=eGftiuyQ3QkcenpEmbZjy_3VomWoXADnQsGUCFoFBvs,6274
|
8
|
-
multiclass_interface/multi_object_list.py,sha256=5bEdwvtzQkPyBrS-W64i3EHJmuTfNGmRhGm5ToK7SXI,2072
|
9
|
-
multiclass_interface/multiprocess_interface.py,sha256=kby28wjkWPBpNEz76NyQlx6GH1h7C-3gKV2-jBTQ37I,7547
|
10
|
-
multiclass_interface/my_test_cls.py,sha256=7ZDsFkxrLfOY6q00U5Y-daxfuhATK-K5H04RP-VmQdE,850
|
11
|
-
h2lib-13.0.707.dist-info/METADATA,sha256=eKyPVPgLJpVJR4QTl1GHXLBUHz4QiCWRI19CdkFzZIg,623
|
12
|
-
h2lib-13.0.707.dist-info/WHEEL,sha256=3SeyPJ5-Us2Ct5GSftUVKtLSlm-bNefW4m5qd0GLzww,100
|
13
|
-
h2lib-13.0.707.dist-info/top_level.txt,sha256=CafRr3oTgH80oaQrp2SGKlPcX7cag5ag4EGKAZAy1ow,27
|
14
|
-
h2lib-13.0.707.dist-info/RECORD,,
|
@@ -1,184 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import sys
|
3
|
-
import os
|
4
|
-
import subprocess
|
5
|
-
import traceback
|
6
|
-
import inspect
|
7
|
-
from enum import Enum
|
8
|
-
|
9
|
-
if 'SLURM_NTASKS' in os.environ:
|
10
|
-
mpi = int(os.environ['SLURM_NTASKS']) > 1
|
11
|
-
elif any([k in os.environ for k in ['MPI_LOCALNRANKS', 'OMPI_COMM_WORLD_SIZE']]):
|
12
|
-
mpi = True
|
13
|
-
else:
|
14
|
-
mpi = subprocess.run("python -c 'from mpi4py import MPI'", shell=True,
|
15
|
-
check=False, stderr=subprocess.PIPE).returncode == 0
|
16
|
-
|
17
|
-
if mpi:
|
18
|
-
from mpi4py import MPI
|
19
|
-
comm = MPI.COMM_WORLD
|
20
|
-
size = MPI.COMM_WORLD.Get_size()
|
21
|
-
rank = MPI.COMM_WORLD.Get_rank()
|
22
|
-
name = MPI.Get_processor_name()
|
23
|
-
else:
|
24
|
-
size = 1
|
25
|
-
|
26
|
-
MPIClassInterfaceAttributes = {'close', 'use_rank', 'cls', 'work_loop', 'object', '__class__','get_input','do_task', 'run_task', 'closed'}
|
27
|
-
|
28
|
-
|
29
|
-
LOOP_UNTIL_CLOSE=True
|
30
|
-
TERMINATE_ON_CLOSE=True
|
31
|
-
|
32
|
-
|
33
|
-
class MPIClassInterface():
|
34
|
-
def __init__(self, cls, args_lst):
|
35
|
-
if len(args_lst) > size:
|
36
|
-
if rank == 0:
|
37
|
-
raise Exception(f"Not enough mpi slots. Slots: {size}, Requested: {len(args_lst)}")
|
38
|
-
return
|
39
|
-
self.cls = cls
|
40
|
-
if rank < len(args_lst):
|
41
|
-
self.object = cls(*args_lst[rank])
|
42
|
-
else:
|
43
|
-
class Dummy():
|
44
|
-
def close(self):
|
45
|
-
pass
|
46
|
-
self.object = Dummy()
|
47
|
-
self.closed=False
|
48
|
-
|
49
|
-
if rank == 0:
|
50
|
-
self.use_rank = np.array([True] * size)
|
51
|
-
self.use_rank[len(args_lst):] = False
|
52
|
-
elif LOOP_UNTIL_CLOSE:
|
53
|
-
self.work_loop()
|
54
|
-
|
55
|
-
def __enter__(self):
|
56
|
-
return self
|
57
|
-
|
58
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
59
|
-
self.close()
|
60
|
-
|
61
|
-
def work_loop(self):
|
62
|
-
while True:
|
63
|
-
method, args, kwargs = comm.scatter(None)
|
64
|
-
comm.gather(self.do_task(method, args, kwargs))
|
65
|
-
if LOOP_UNTIL_CLOSE:
|
66
|
-
if method == 'close':
|
67
|
-
if TERMINATE_ON_CLOSE:
|
68
|
-
#comm.gather(f'Exit, rank {rank}')
|
69
|
-
print ("sys.exit", rank, flush=True)
|
70
|
-
sys.exit(0)
|
71
|
-
else:
|
72
|
-
raise ChildProcessError('MPI worker done')
|
73
|
-
else:
|
74
|
-
break
|
75
|
-
|
76
|
-
|
77
|
-
def do_task(self, method, args, kwargs):
|
78
|
-
try:
|
79
|
-
if method == 'skip':
|
80
|
-
res = None
|
81
|
-
elif method=='setattr':
|
82
|
-
name, value = args
|
83
|
-
if hasattr(value, '__call__'):
|
84
|
-
def wrap(*args, func=value, **kwargs):
|
85
|
-
if inspect.getfullargspec(func).args[:1] == ['self']:
|
86
|
-
args = (self.object,) + args
|
87
|
-
return func(*args, **kwargs)
|
88
|
-
value = wrap
|
89
|
-
res = setattr(self.object, name, value)
|
90
|
-
else:
|
91
|
-
res = getattr(self.object, method)
|
92
|
-
if hasattr(res, '__call__'):
|
93
|
-
res = res(*args, **kwargs)
|
94
|
-
except BaseException as e:
|
95
|
-
res = (e, traceback.format_exc())
|
96
|
-
return res
|
97
|
-
|
98
|
-
def run_task(self, input_lst):
|
99
|
-
comm.scatter(input_lst, root=0)
|
100
|
-
if rank == 0:
|
101
|
-
method, args, kwargs = input_lst[0]
|
102
|
-
res = self.do_task(method, args, kwargs)
|
103
|
-
else:
|
104
|
-
res = None
|
105
|
-
use_rank = self.use_rank
|
106
|
-
|
107
|
-
res = [res for i, res in enumerate(comm.gather(res, root=0)) if use_rank[i]]
|
108
|
-
if rank==0:
|
109
|
-
for r in res:
|
110
|
-
if isinstance(r, tuple) and len(r) > 1 and isinstance(r[0], BaseException):
|
111
|
-
raise r[0].__class__(r[1])
|
112
|
-
return res
|
113
|
-
|
114
|
-
|
115
|
-
def get_input(self, name, i, args, kwargs):
|
116
|
-
use_rank = self.use_rank
|
117
|
-
N = np.sum(use_rank)
|
118
|
-
if use_rank[i]:
|
119
|
-
def get_arg(arg):
|
120
|
-
if isinstance(arg, list) and len(arg) == N:
|
121
|
-
return arg[np.where(use_rank)[0][i]]
|
122
|
-
else:
|
123
|
-
return arg
|
124
|
-
return (name, [get_arg(arg) for arg in args], {k: get_arg(v) for k, v in kwargs.items()})
|
125
|
-
else:
|
126
|
-
return ('skip', [], {})
|
127
|
-
|
128
|
-
def __getattribute__(self, name):
|
129
|
-
if name in MPIClassInterfaceAttributes:
|
130
|
-
return object.__getattribute__(self, name)
|
131
|
-
elif rank > 0:
|
132
|
-
self.work_loop()
|
133
|
-
return lambda *args, **kwargs:1
|
134
|
-
|
135
|
-
def wrap(*args, **kwargs):
|
136
|
-
inp = [self.get_input(name, i, args, kwargs) for i in range(size)]
|
137
|
-
return self.run_task(inp)
|
138
|
-
|
139
|
-
if hasattr(getattr(self.object, name), '__call__'):
|
140
|
-
return wrap
|
141
|
-
else:
|
142
|
-
return wrap()
|
143
|
-
|
144
|
-
def __setattr__(self, name, value):
|
145
|
-
if rank > 0 or name in MPIClassInterfaceAttributes:
|
146
|
-
return object.__setattr__(self, name, value)
|
147
|
-
else:
|
148
|
-
inp = [self.get_input('setattr', i, (name, value), {}) for i in range(size)]
|
149
|
-
return self.run_task(inp)
|
150
|
-
|
151
|
-
|
152
|
-
def __getitem__(self, slice):
|
153
|
-
use_rank = np.full_like(self.use_rank, False)
|
154
|
-
use_rank[slice] = True
|
155
|
-
if np.all(self.use_rank == use_rank):
|
156
|
-
return self
|
157
|
-
return SubsetMPIClassInterface(self.cls, self.object, use_rank)
|
158
|
-
|
159
|
-
def close(self):
|
160
|
-
if not self.closed:
|
161
|
-
if rank==0:
|
162
|
-
res = self.run_task([('close', [], {}) for _ in range(size)])
|
163
|
-
else:
|
164
|
-
self.work_loop()
|
165
|
-
res = None
|
166
|
-
self.closed=True
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
class SubsetMPIClassInterface(MPIClassInterface):
|
172
|
-
def __init__(self, cls, object, use_rank):
|
173
|
-
self.use_rank = use_rank
|
174
|
-
self.cls = cls
|
175
|
-
self.object = object
|
176
|
-
|
177
|
-
def __getitem__(self, slice):
|
178
|
-
l = np.arange(np.sum(self.use_rank))
|
179
|
-
if np.all(l == l[slice]):
|
180
|
-
return self
|
181
|
-
raise Exception('Cannot make subset of SubsetMPIClassInterface')
|
182
|
-
|
183
|
-
def close(self):
|
184
|
-
raise Exception('Cannot close SubsetMPIClassInterface. Please close all instances at once')
|
@@ -1,57 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
|
3
|
-
|
4
|
-
class MultiObjectList():
|
5
|
-
def __init__(self, obj_lst, subset_cls=None):
|
6
|
-
self.obj_lst = np.atleast_1d(obj_lst)
|
7
|
-
self.subset_cls = subset_cls
|
8
|
-
|
9
|
-
def __str__(self):
|
10
|
-
return f'{self.__class__.__name__}({self.obj_lst})'
|
11
|
-
|
12
|
-
def get_obj_args_lst(self, args, kwargs):
|
13
|
-
N = len(self.obj_lst)
|
14
|
-
|
15
|
-
def get_obj_args(i):
|
16
|
-
def get_arg(arg):
|
17
|
-
if isinstance(arg, list) and len(arg) == N:
|
18
|
-
return arg[i]
|
19
|
-
else:
|
20
|
-
return arg
|
21
|
-
obj_args = [get_arg(arg) for arg in args]
|
22
|
-
obj_kwargs = {k: get_arg(v) for k, v in kwargs.items()}
|
23
|
-
return obj_args, obj_kwargs
|
24
|
-
return [get_obj_args(i) for i in range(N)]
|
25
|
-
|
26
|
-
def iscallable(self, name):
|
27
|
-
return hasattr(getattr(self.obj_lst[0], name), '__call__')
|
28
|
-
|
29
|
-
def __getitem__(self, s):
|
30
|
-
obj_lst = np.atleast_1d(self.obj_lst[s])
|
31
|
-
if len(obj_lst) == len(self.obj_lst) and np.all(obj_lst == self.obj_lst):
|
32
|
-
return self
|
33
|
-
subset_cls = self.subset_cls or MultiObjectList
|
34
|
-
return subset_cls(self.obj_lst[s])
|
35
|
-
|
36
|
-
def __getattr__(self, name):
|
37
|
-
att_lst = [getattr(obj, name) for obj in self.obj_lst]
|
38
|
-
if self.iscallable(name):
|
39
|
-
def wrap(*args, **kwargs):
|
40
|
-
return [att(*o_args, **o_kwargs)
|
41
|
-
for att, (o_args, o_kwargs) in zip(att_lst, self.get_obj_args_lst(args, kwargs))]
|
42
|
-
return wrap
|
43
|
-
else:
|
44
|
-
return att_lst
|
45
|
-
|
46
|
-
def __setattr__(self, name, value):
|
47
|
-
if name in {'obj_lst', 'subset_cls'}:
|
48
|
-
return object.__setattr__(self, name, value)
|
49
|
-
obj_lst = self.obj_lst
|
50
|
-
for obj, (o_args, _) in zip(obj_lst, self.get_obj_args_lst((value,), {})):
|
51
|
-
setattr(obj, name, *o_args)
|
52
|
-
|
53
|
-
|
54
|
-
class MultiClassInterface(MultiObjectList):
|
55
|
-
def __init__(self, cls, args_lst):
|
56
|
-
self.cls = cls
|
57
|
-
MultiObjectList.__init__(self, [cls(*args) for args in args_lst])
|
@@ -1,193 +0,0 @@
|
|
1
|
-
import multiprocessing
|
2
|
-
import atexit
|
3
|
-
import numpy as np
|
4
|
-
from threading import Thread
|
5
|
-
from functools import wraps
|
6
|
-
import traceback
|
7
|
-
from _queue import Empty
|
8
|
-
import os
|
9
|
-
from contextlib import contextmanager
|
10
|
-
import sys
|
11
|
-
import inspect
|
12
|
-
from multiclass_interface.multi_object_list import MultiObjectList
|
13
|
-
|
14
|
-
|
15
|
-
def run(cls, inputQueue, outputQueue, cls_args, **kwargs):
|
16
|
-
o = cls(*cls_args, **kwargs)
|
17
|
-
while True:
|
18
|
-
method, args, kwargs = inputQueue.get()
|
19
|
-
try:
|
20
|
-
if method == 'getattr':
|
21
|
-
name = args[0]
|
22
|
-
outputQueue.put(getattr(o, name))
|
23
|
-
elif method == 'setattr':
|
24
|
-
name, value = args
|
25
|
-
if hasattr(value, '__call__'): # pragma: no cover # cov not registered?
|
26
|
-
|
27
|
-
def wrap(*args, func=value, **kwargs):
|
28
|
-
if inspect.getfullargspec(func).args[:1] == ['self']:
|
29
|
-
args = (o,) + args
|
30
|
-
return func(*args, **kwargs)
|
31
|
-
outputQueue.put(setattr(o, name, wrap))
|
32
|
-
else:
|
33
|
-
outputQueue.put(setattr(o, name, value))
|
34
|
-
elif method == 'iscallable':
|
35
|
-
name = args[0]
|
36
|
-
outputQueue.put(hasattr(getattr(o, name), '__call__'))
|
37
|
-
else:
|
38
|
-
att = getattr(o, method)
|
39
|
-
outputQueue.put(att(*args, **kwargs))
|
40
|
-
except BaseException as e:
|
41
|
-
outputQueue.put((e, traceback.format_exc()))
|
42
|
-
finally:
|
43
|
-
if method == 'close':
|
44
|
-
outputQueue.put('Exit process')
|
45
|
-
return
|
46
|
-
|
47
|
-
|
48
|
-
class ProcessClass():
|
49
|
-
cls = None
|
50
|
-
|
51
|
-
def __init__(self, cls, cls_attrs={}):
|
52
|
-
self.cls_attrs = cls_attrs
|
53
|
-
self.cls = cls
|
54
|
-
self.ctx = multiprocessing.get_context('spawn')
|
55
|
-
self.inputQueue = self.ctx.Queue()
|
56
|
-
self.outputQueue = self.ctx.Queue()
|
57
|
-
atexit.register(self.close)
|
58
|
-
self.closed = False
|
59
|
-
|
60
|
-
def __call__(self, *args, **kwargs):
|
61
|
-
kwargs.update({'cls': self.cls, 'inputQueue': self.inputQueue, 'outputQueue': self.outputQueue,
|
62
|
-
'cls_args': args})
|
63
|
-
s = 'vs_debug.py'
|
64
|
-
if s in "".join(traceback.format_stack()): # pragma: no cover
|
65
|
-
self.process = Thread(target=run, kwargs=kwargs) # use this to debug from Visual studio
|
66
|
-
else:
|
67
|
-
self.process = self.ctx.Process(target=run, kwargs=kwargs, daemon=True)
|
68
|
-
|
69
|
-
self.process.start()
|
70
|
-
return self
|
71
|
-
|
72
|
-
def __enter__(self):
|
73
|
-
return self
|
74
|
-
|
75
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
76
|
-
self.close()
|
77
|
-
|
78
|
-
def __getattribute__(self, name):
|
79
|
-
try:
|
80
|
-
if name != 'cls_attrs' and name in self.cls_attrs:
|
81
|
-
raise AttributeError()
|
82
|
-
return object.__getattribute__(self, name)
|
83
|
-
except AttributeError:
|
84
|
-
return self.getattr(name, None)
|
85
|
-
|
86
|
-
def getattr(self, name, is_callable):
|
87
|
-
if is_callable is None:
|
88
|
-
is_callable = self.is_callable(name)
|
89
|
-
if is_callable:
|
90
|
-
@wraps(getattr(self.cls, name, None))
|
91
|
-
def wrap(*args, wait_for_result=True, **kwargs):
|
92
|
-
self.inputQueue.put((name, args, kwargs))
|
93
|
-
if wait_for_result:
|
94
|
-
return self.get_result(raise_exception=True,
|
95
|
-
cmd=lambda: f'executing {name}({", ".join(list(map(str,args))+["%s=%s"%(k,v) for k,v in kwargs.items()])})')
|
96
|
-
return wrap
|
97
|
-
else:
|
98
|
-
self.inputQueue.put(('getattr', (name,), {}))
|
99
|
-
return self.get_result(raise_exception=True, cmd=lambda: f"getting attribute '{name}'")
|
100
|
-
|
101
|
-
def is_callable(self, name):
|
102
|
-
self.inputQueue.put(('iscallable', (name,), {}))
|
103
|
-
return self.get_result(raise_exception=True, cmd=lambda: f"checking if '{name}' is callable")
|
104
|
-
|
105
|
-
def __setattr__(self, name, value):
|
106
|
-
if name in {'cls', 'ctx', 'inputQueue', 'outputQueue', 'closed', 'process', 'cls_attrs'}:
|
107
|
-
return object.__setattr__(self, name, value)
|
108
|
-
else:
|
109
|
-
self.inputQueue.put(('setattr', (name, value), {}))
|
110
|
-
return self.get_result(raise_exception=True, cmd=lambda: f"setting attribute '{name}'")
|
111
|
-
|
112
|
-
def get_result(self, raise_exception, cmd):
|
113
|
-
while True:
|
114
|
-
if self.process.is_alive() or self.closed:
|
115
|
-
try:
|
116
|
-
res = self.outputQueue.get(timeout=2)
|
117
|
-
if isinstance(res, tuple) and len(res) > 1 and isinstance(res[0], BaseException):
|
118
|
-
res = res[0].__class__(res[1])
|
119
|
-
if raise_exception:
|
120
|
-
raise res
|
121
|
-
return res
|
122
|
-
except Empty:
|
123
|
-
pass # time out. Check process is alive and try again
|
124
|
-
else:
|
125
|
-
if hasattr(cmd, '__call__'):
|
126
|
-
cmd = cmd()
|
127
|
-
e = Exception(f'{self.cls.__name__} process died before or while {cmd}')
|
128
|
-
if raise_exception:
|
129
|
-
raise e
|
130
|
-
return e
|
131
|
-
|
132
|
-
def close(self, wait_for_result=False):
|
133
|
-
if not self.closed:
|
134
|
-
self.inputQueue.put(('close', [], {}))
|
135
|
-
r = self.get_result(False, 'close')
|
136
|
-
self.get_result(False, 'get process exit message')
|
137
|
-
self.process.join()
|
138
|
-
self.inputQueue.close()
|
139
|
-
self.outputQueue.close()
|
140
|
-
self.closed = True
|
141
|
-
return r
|
142
|
-
|
143
|
-
|
144
|
-
class MultiProcessClassInterface(MultiObjectList):
|
145
|
-
|
146
|
-
def __init__(self, cls, args_lst, cls_attrs={}):
|
147
|
-
MultiObjectList.__init__(self, [ProcessClass(cls, cls_attrs)(*args) for args in args_lst], SubsetProcessWrapper)
|
148
|
-
|
149
|
-
def __getattr__(self, name):
|
150
|
-
obj_lst = self.obj_lst
|
151
|
-
if obj_lst[0].is_callable(name):
|
152
|
-
def wrap(*args, **kwargs):
|
153
|
-
for obj, (o_args, o_kwargs) in zip(obj_lst, self.get_obj_args_lst(args, kwargs)):
|
154
|
-
obj.getattr(name, True)(*o_args, wait_for_result=False, **o_kwargs)
|
155
|
-
res = [o.get_result(raise_exception=False, cmd=lambda: f"executing {name}(...)")
|
156
|
-
for o in obj_lst]
|
157
|
-
for r in res:
|
158
|
-
if isinstance(r, Exception):
|
159
|
-
raise r
|
160
|
-
return res
|
161
|
-
return wrap
|
162
|
-
else:
|
163
|
-
return [o.getattr(name, False) for o in obj_lst]
|
164
|
-
|
165
|
-
def __enter__(self):
|
166
|
-
return self
|
167
|
-
|
168
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
169
|
-
self.close()
|
170
|
-
|
171
|
-
def close(self, wait_for_result=False):
|
172
|
-
for obj in self.obj_lst:
|
173
|
-
obj.close()
|
174
|
-
# if not obj.closed:
|
175
|
-
# obj.inputQueue.put(('close', [], {}))
|
176
|
-
# obj.process.join()
|
177
|
-
# obj.closed = True
|
178
|
-
|
179
|
-
|
180
|
-
class SubsetProcessWrapper(MultiProcessClassInterface):
|
181
|
-
def __init__(self, obj_lst):
|
182
|
-
MultiObjectList.__init__(self, obj_lst)
|
183
|
-
|
184
|
-
def __getitem__(self, slice):
|
185
|
-
if np.all(np.atleast_1d(self.obj_lst[slice]) == self.obj_lst):
|
186
|
-
return self
|
187
|
-
raise Exception('Cannot make subset of SubsetProcessWrapper')
|
188
|
-
|
189
|
-
def __getattribute__(self, name):
|
190
|
-
if name == 'close':
|
191
|
-
raise Exception("Cannot close SubsetProcessWrapper. Please close all instances at once")
|
192
|
-
|
193
|
-
return MultiProcessClassInterface.__getattribute__(self, name)
|
@@ -1,33 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
import os
|
3
|
-
|
4
|
-
|
5
|
-
class MyTest():
|
6
|
-
def __init__(self, id):
|
7
|
-
self.id = id
|
8
|
-
self.name = self.__class__.__name__
|
9
|
-
|
10
|
-
def get_id(self,):
|
11
|
-
return self.id
|
12
|
-
|
13
|
-
def work(self, t):
|
14
|
-
start_time = time.time()
|
15
|
-
s1 = f'{self.id} starts working for {t}s at t={start_time}. '
|
16
|
-
# print (s1)
|
17
|
-
while time.time() < start_time + t:
|
18
|
-
pass
|
19
|
-
s2 = f'{self.id} ends working at {time.time()}.'
|
20
|
-
# print (s2)
|
21
|
-
return s1 + s2
|
22
|
-
|
23
|
-
def return_input(self, *args, **kwargs):
|
24
|
-
return f"{self.id} got: {str(args)} and {str(kwargs)}"
|
25
|
-
|
26
|
-
def get_ld_library_path(self):
|
27
|
-
return os.environ['LD_LIBRARY_PATH']
|
28
|
-
|
29
|
-
def close(self):
|
30
|
-
return f"closing {self.get_id()}"
|
31
|
-
|
32
|
-
def raise_exception(self):
|
33
|
-
1 / 0 # raise ZeroDivisionError
|