I expected that if I'd call apply_async
in an instance method and get its result, that any changes made would stay part of the forked processes. However, it seems that every new call to apply_async creates a new copy of said instance.
Take the following code:
from multiprocessing.pool import Pool
class Multitest:
def __init__(self):
self.i = 0
def run(self):
with Pool(2) as pool:
worker_jobs = []
for j in range(10):
job = pool.apply_async(self.process, (j,))
worker_jobs.append(job)
for job in worker_jobs:
res = job.get()
print("input", res)
def process(self, inp):
print("i", self.i)
self.i += 1
return inp
if __name__ == '__main__':
mt = Multitest()
mt.run()
Sample output:
i 0
i 0
i 0
i 0
i 0
input 0
i 0
i 0
i 0
i 0
i 0
input 1
input 2
input 3
input 4
input 5
input 6
input 7
input 8
input 9
But since we have two cores over which 10 inputs are spread, I had expected the i
properties to be incremented.
I had expected the following flow:
- main thread creates instance and calls
run()
- main thread distributes work of
apply_async
over pool by initializing two new processes and a copy of the original Multitest instance (wherei = 0
) process()
is called on the new processes a number of times (untilrange()
is exhausted). On each call to process,self.i
for that process is incremented
Note: I am not asking after the shared state between two processes. Instead I am asking why the class instance of a single process is not mutated (why isn't each individual process's self.i
not incremented).
However, I do not see this behaviour. Instead, the printed output is only zeroes, indicating that my expectations were wrong: the state (property i
) is not maintained, but a new instance (or at least a new copy) is created on every call to apply_async
. What am I missing here, and how can I make this work as expected? (Preferably with apply_async
, though not required. The order of the results should be maintained, though.)
As far as I can tell this behaviour is not specific to apply_async
but also to the other pool
methods. I am interested to learn why this happens and how the behaviour can be changed to the behaviour I want to achieve. Bounty goes to the answer that can provide an answer to both queries.