0

I have a python program as follows

def send_request(data):
    global lock
    lock.acquire()
    print(data)
    lock.release()

if __name__ == '__main__':
    data_list = ['data1', 'data2', 'data3']
    lock = multiprocessing.Lock()
    pool = multiprocessing.Pool(3)

    pool.map(send_request, data_list)
    pool.close()
    pool.join()

Why did this error occur? NameError: name 'lock' is not defined.

updated

In the answer below, @Jean-François Fabre said that the reason is because “When running your subprocesses, python is "forking" and doesn't see the lock declaration, because it doesn't execute the __main__ part in subprocesses.” But in the following example, the subprocess should not see the lock definition too, but why is the program working fine?

import multiprocessing

def send_request(data):
   lock.acquire()
   print(data,' ',os.getpid())
   lock.release()

def init(l):
   global lock
   lock = l

if __name__ == '__main__':
   data_list = ['data1', 'data2', 'data3']
   lock = multiprocessing.Lock()
   pool = multiprocessing.Pool(8, initializer=init, initargs=(lock,))
   pool.map(send_request, data_list)
   pool.close()
   pool.join()
wjandrea
  • 28,235
  • 9
  • 60
  • 81
inaMinute
  • 553
  • 2
  • 7
  • 16

1 Answers1

1

In the context of multiprocessing, you have to do more than that.

When running your subprocesses, python is "forking" and doesn't see the lock declaration, because it doesn't execute the __main__ part in subprocesses.

Plus, on Windows (which doesn't have fork, the forking is emulated, leading to different behaviour compared to Unix-like platforms: in a nutshell, fork is able to resume the new process where the old process started, but on Windows, Python has to run a new process from the beginning and take control afterwards, this leads to side effects)

You have to create your lock as a global variable outside the __main__ test (and you can drop global keyword, it will work without it)

import multiprocessing

lock = multiprocessing.Lock()

def send_request(data):
    lock.acquire()
    print(data)
    lock.release()

with those modifications your program prints

data1
data2
data3

as expected.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219