Search code examples
pythonpython-3.xpython-multiprocessing

Proper way to share a list between processes?


I wanted to set up two subprocesses in which subprocess1 keeps generating data (in type of list), and subprocess2 is in charge of processing the data sent from subprocess1.

I used multiprocessing.Manager().list() to create a shared list. But this is the error it reports:

FileNotFoundError: [WinError 2]

Code

I simplified the code as below: ps: need to run it in terminal.

import multiprocessing as mp
import random
import time

def generator(a, b, tick): # simulating data collection,and a list will be generated at random and passed to another shared list.
    counter = 0
    while True:
        time.sleep(1)
        a.append([random.uniform(1,5), random.uniform(1,5), random.uniform(1,5), random.uniform(1,5)])
        counter += 1
        print('generate says', a[:])
        if counter%5 == 0:
            b.append(a[:])
            tick.value = 1  # Telling 'printer' func to print.
            for _ in a:
                a.remove(_)
       
def printer(b, tick):  # simulating data processing, and only printing data received from the 'generator' func here.
    while True:
        time.sleep(1)
        if tick.value == 1:
            time.sleep(1)
            print('printer says', b[:])
            tick.value = 0 
            for _ in b:
                b.remove(_)
        
if __name__=='__main__':
    tick=mp.Value('i', 0)
    a = mp.Manager().list()
    b = mp.Manager().list()
    p1 = mp.Process(target=generator, args=(a, b, tick))
    p2 = mp.Process(target=printer, args=(b, tick))
    p1.start()
    p2.start()

Error

Traceback (most recent call last):
  File "d:\miniconda\lib\multiprocessing\process.py", line 297, in _bootstrap
    self.run()
  File "d:\miniconda\lib\multiprocessing\process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Program Files (x86)\onedrive\nilm\pi\redd\niubi.py", line 9, in generater
    a.append([random.uniform(1,5),random.uniform(1,5),random.uniform(1,5),random.uniform(1,5)])
  File "<string>", line 2, in append
  File "d:\miniconda\lib\multiprocessing\managers.py", line 792, in _callmethod
    self._connect()
  File "d:\miniconda\lib\multiprocessing\managers.py", line 779, in _connect
    conn = self._Client(self._token.address, authkey=self._authkey)
  File "d:\miniconda\lib\multiprocessing\connection.py", line 490, in Client
    c = PipeClient(address)
  File "d:\miniconda\lib\multiprocessing\connection.py", line 691, in PipeClient
    _winapi.WaitNamedPipe(address, 1000)
FileNotFoundError: [WinError 2] The system cannot find the file specified.

Solution

  • There were a few things to fix, but the primary issue is that you should include Process.join, as seen below:

    import multiprocessing as mp
    import random
    import time
    
    ...  # generator and printer definitions are unchanged
    
    if __name__=='__main__':
        manager = mp.Manager()  # Create an instance of the manager
        a = manager.list()
        b = manager.list()
        tick = mp.Value('i', 0)
        p1 = mp.Process(target=generator, args=(tick, a, b))
        p2 = mp.Process(target=printer, args=(tick, b))
        p1.start()
        p2.start()
        p1.join()  # Join, to ensure p1 and p2 end
        p2.join()