Python多进程报错NameError: name 'lock' is not defined的原因及疑问
Great question! Let's break down why your first code fails and the second one works perfectly, focusing on how Python's multiprocessing handles shared resources and child process initialization.
The Problem with Your First Code
Let's look at the problematic snippet first:
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()
When you create a Pool of processes, each child process behaves in one of two ways depending on your OS:
- On Unix-like systems: The child is forked from the parent, but it doesn't re-run the
__main__code block. Since yourlockvariable is defined inside__main__, the child process never gets a reference to it—so the globallockthatsend_requesttries to access doesn't exist. - On Windows: The child process starts fresh, re-imports your script, and skips the
__main__block entirely (to avoid infinite spawning loops). Again, thelockvariable is never initialized in the child's context.
Either scenario leads to the NameError: name 'lock' is not defined when send_request runs in a child process.
Why the Second Code Works
Now let's look at your working example (note: I added the missing os import to avoid another error):
import multiprocessing import os 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()
The magic here is the Pool's initializer and initargs parameters:
- Every time a child process is created in the pool, it immediately runs the
initializerfunction (init) with the arguments passed ininitargs(your sharedlockobject). - The
initfunction sets the globallockvariable in the child process to the valid lock object from the parent.
By the time send_request runs in the child, the global lock is already initialized and points to a working shared lock. This approach is cross-platform safe because it explicitly sets up required resources in each child, instead of relying on variables that only exist in the parent's __main__ block.
内容的提问来源于stack exchange,提问作者inaMinute

