Question presented to candidate:
"Threads in one Python process can all see the same list. Separate processes cannot. So when you use multiprocessing, how does data actually get from one process to another โ and when would you pick a queue, a shared Value, shared_memory or a Manager?"
What a strong answer should cover:
- Each process has its own memory (address space), so by default nothing is shared: arguments, queue items and return values are pickled, sent over a pipe, and unpickled as a copy on the other side. Mutating the copy never changes the original, and unpicklable objects (lambdas, locks, generators, open sockets) cannot be sent at all.
- Message passing with
Queue(many producers/consumers, a feeder thread plus a pipe underneath) andPipe(two connected ends) is the default, safest design. - Real shared memory:
Value/Array(ctypes objects in shared memory, with a lock for read-modify-write) andmultiprocessing.shared_memory.SharedMemory(raw named bytes, zero-copy, added in 3.8, withclose()per process and exactly oneunlink()). Managerobjects: a server process owns the real dict/list and others call it through proxies โ flexible but every operation is a round trip, and mutating a nested object through a proxy is silently lost.- Start methods matter:
forkcopies the parent (copy-on-write),spawnstarts a fresh interpreter and re-imports the main module (henceif __name__ == "__main__":),forkserverforks from a clean server; Linux defaults toforkup to 3.13 and toforkserverfrom 3.14, macOS and Windows usespawn.
Clarifying questions expected:
- How big is the data, and is it read-only or updated by many workers?
- Which OS and Python version (it decides the default start method)?
Code / implementation expected: Optional โ a worker fed by a Queue, or a counter in a Value guarded by its lock.