The warnings.catch_warnings() context manager is not thread safe. How do I use it in a parallel processing environment?
The unpickling would not cause the __init__
to be executed twice. I ran the following code on Windows, and it doesn't happen (each __init__
is run precisely once).
Therefore, you need to provide us with the code from my_load_balancer
and from widgets' class. At this point, your question simply doesn't provide enough information.
As a random guess, you might check whether my_load_balancer
makes copies of widgets, causing them to be instantiated once again.
import multiprocessing
import collections
"Call `frobnicate(list_of_widgets)` to get the widget with the most frobnals"
def my_load_balancer(widgets):
partitions = tuple(set() for _ in range(8))
for i, widget in enumerate(widgets):
partitions[i % 8].add(widget)
for partition in partitions:
yield partition
def my_frobnal_counter(widget):
return widget.id
def frobnicate_parallel_worker(widgets, output_queue):
resultant_widget = max(widgets, key=my_frobnal_counter)
output_queue.put(resultant_widget)
def frobnicate_parallel(widgets):
output_queue = multiprocessing.Queue()
# partitions: Generator yielding tuples of sets
partitions = my_load_balancer(widgets)
processes = []
# Line A: Possible start of where the warnings are coming from.
for partition in partitions:
p = multiprocessing.Process(
target=frobnicate_parallel_worker,
args=(partition, output_queue))
processes.append(p)
p.start()
finalists = []
for p in processes:
finalists.append(output_queue.get())
# Avoid deadlocks in Unix by draining queue before joining processes
for p in processes:
p.join()
# Line B: Warnings no longer possible after here.
return max(finalists, key=my_frobnal_counter)
class Widget:
id = 0
def __init__(self):
print('initializing Widget {}'.format(self.id))
self.id = Widget.id
Widget.id += 1
def __str__(self):
return str(self.id)
def __repr__(self):
return str(self)
def main():
widgets = [Widget() for _ in range(16)]
result = frobnicate_parallel(widgets)
print(result.id)
if __name__ == '__main__':
main()