Python > Advanced Python Concepts > Concurrency and Parallelism > Processes and the `multiprocessing` Module
Inter-Process Communication with Queues
This code demonstrates how to use `multiprocessing.Queue` for inter-process communication. It creates a producer process that puts data into a queue and a consumer process that retrieves data from the queue. This pattern is useful for scenarios where processes need to exchange data or synchronize their activities.
Code Snippet
This code creates a `multiprocessing.Queue` for communication between two processes. The `producer` process puts random numbers into the queue, and the `consumer` process retrieves and prints them. A sentinel value (`None`) is used to signal the consumer to terminate after the producer is finished. The `producer.join()` ensures that the producer has finished putting values in the queue before the sentinel is sent. The `consumer.join()` ensures that the consumer process has terminated gracefully.
import multiprocessing
import time
import random
def producer(queue):
"""Producer process that puts numbers into the queue."""
for i in range(5):
number = random.randint(1, 100)
queue.put(number)
print(f"Producer: Put {number} into the queue.")
time.sleep(random.random())
def consumer(queue):
"""Consumer process that retrieves numbers from the queue."""
while True:
number = queue.get()
if number is None: # Sentinel value to signal end of processing
print("Consumer: Received termination signal.")
break
print(f"Consumer: Got {number} from the queue.")
time.sleep(random.random())
if __name__ == '__main__':
queue = multiprocessing.Queue()
producer_process = multiprocessing.Process(target=producer, args=(queue,))
consumer_process = multiprocessing.Process(target=consumer, args=(queue,))
producer_process.start()
consumer_process.start()
producer_process.join()
queue.put(None) # Signal consumer to terminate
consumer_process.join() # Important! wait for the consumer process to terminate
print("Done!")
Concepts Behind the Snippet
This snippet utilizes the following key concepts:
Real-Life Use Case
This pattern is applicable in various scenarios:
Best Practices
Interview Tip
Be prepared to discuss:
When to Use Them
Use `multiprocessing.Queue` when:
Memory Footprint
The memory footprint of a `multiprocessing.Queue` depends on the size of the items being stored in the queue and the maximum size of the queue. Large queues with large items can consume significant memory. Be mindful of this when designing your application and consider limiting the queue size if necessary.
Alternatives
Alternatives to `multiprocessing.Queue` for IPC include:
Pros
Cons
FAQ
-
What is a sentinel value and why is it used?
A sentinel value is a special value that is used to signal the end of processing to consumer processes. It allows consumer processes to terminate gracefully when there is no more data to process. -
How can I prevent a queue from growing indefinitely?
You can set a maximum size for the queue when creating it using `queue = multiprocessing.Queue(maxsize=...)`. When the queue is full, `queue.put()` will block until space becomes available. -
Is `multiprocessing.Queue` suitable for sharing large amounts of data?
For sharing very large amounts of data, consider using shared memory or memory-mapped files instead of queues, as they can offer better performance by avoiding data copying. However, queues provide convenient synchronization and are often preferred for moderate data sizes.