进程间通信
进程管道通信
进程是程序运行的基本单位,每个进程都有自己的数据和程序单元,普通进程的地址空间彼此隔离,不能直接访问对方的私有数据。但是可以通过特定的管道实现进程间I/O。
工作进程
写读
进程管道
读写
工作进程
创建进程通信管道
import multiprocessing
def send_data(pipe, data):
pipe.send(data)
print("[Process %d] Sent: %s" % (
multiprocessing.current_process().pid,
data
))
def recv_data(pipe):
print("[Process %d] Received: %s" % (
multiprocessing.current_process().pid,
pipe.recv()
))
def main():
send_end, recv_end = multiprocessing.Pipe()
sender = multiprocessing.Process(
target=send_data,
args=(send_end, "Hello!")
)
receiver = multiprocessing.Process(
target=recv_data,
args=(recv_end,)
)
sender.start()
receiver.start()
if __name__ == "__main__":
main()运行结果
[Process 4612] Sent: Hello!
[Process 6292] Received: Hello!生产者/消费者问题(Producer/Consumer Problem)
不同的进程彼此之间可以利用管道实现数据的发送和接收,但是如果发送的数据过多并且接收处理缓慢,这种情况下就需要引入队列来进行缓冲。
生产进程
put
进程队列
get
消费进程
multiprocessing.Queue是Python多进程编程中提供的进程队列结构,该队列采用FIFO的形式实现不同进程间的数据通信。同一生产者发送的数据可以按发送顺序接收,不同生产者的消息可能交错。
进程队列
import multiprocessing
import time
def produce(queue):
for item in range(3):
time.sleep(2)
data = "data-%d" % item
print("[%s] Produced: %s" % (
multiprocessing.current_process().name,
data
))
queue.put(data)
queue.put(None)
def consume(queue):
while True:
data = queue.get()
if data is None:
return
print("[%s] Consumed: %s" % (
multiprocessing.current_process().name,
data
))
def main():
queue = multiprocessing.Queue()
producer = multiprocessing.Process(
target=produce, name="Producer",
args=(queue,)
)
consumer = multiprocessing.Process(
target=consume, name="Consumer",
args=(queue,)
)
producer.start()
consumer.start()
if __name__ == "__main__":
main()运行结果
[Producer] Produced: data-0
[Consumer] Consumed: data-0
[Producer] Produced: data-1
[Consumer] Consumed: data-1
[Producer] Produced: data-2
[Consumer] Consumed: data-2互动实验
小商店:生产者、仓库与消费者
访问权限PRO
PRO EXCLUSIVE探索不止于此
尊享 Pro 权益解锁完整互动实验、进阶解析与精选参考答案。
知识测验
题目
有界队列已满,阻塞式生产者应怎样?
动手练习
编程:网店订单的生产与打包
使用Python multiprocessing模拟网店接单与较慢的打包处理。每笔订单包含订单编号、商品名称与数量。
- 创建生产者进程,将ORD-001至ORD-006共六笔订单放入maxsize=3的Queue;每笔订单购买两本Notebook。
- 创建消费者进程,每次取出一笔订单,用0.2秒模拟打包,打印订单编号、商品名称与数量。队列满或空时使用put/get的阻塞行为,不轮询。
- 最后一笔订单之后发送None结束标记。确保六笔订单按FIFO顺序各打包一次、两个子进程都能退出,主进程等待它们后关闭队列。