python的pipe和queue及celery的使用方法

本文介绍了Python的multiprocessing模块中的Pipe和Queue,详细讲解了它们的工作原理和使用方法,强调了Pipe的单双工特性及Queue的多进程交互能力。此外,还探讨了Celery这一分布式任务队列的使用,包括Brokers、Result Stores、Workers和Tasks的概念,并给出了使用Redis作为broker和backend的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

multiprocessing.Pipe()

multiprocessing.Pipe()即管道模式,调用Pipe()返回管道的两端的Connection。

Python官方文档的描述:
Returns a pair (conn1, conn2) of Connection objects representing the ends of a pipe.
因此, Pipe仅仅适用于只有两个进程一读一写的单双工情况,也就是说信息是只向一个方向流动。例如电视、广播,看电视的人只能看,电视台是能播送电视节目。

Pipe的读写效率要高于Queue。
进程间的Pipe基于fork机制建立。
当主进程创建Pipe的时候,Pipe的两个Connections连接的的都是主进程。
当主进程创建子进程后,Connections也被拷贝了一份。此时有了4个Connections。
此后,关闭主进程的一个Out Connection,关闭一个子进程的一个In Connection。那么就建立好了一个输入在主进程,输出在子进程的管道。

  • 实例代码
from multiprocessing import Pipe, Process


def son_process(x, pipe):
    _out_pipe, _in_pipe = pipe

    # 关闭fork过来的输入端
    _in_pipe.close()
    while True:
        try:
            msg = _out_pipe.recv()
            print(msg)
        except EOFError:
            # 当out_pipe接受不到输出的时候且输入被关闭的时候,会抛出EORFError,可以捕获并且退出子进程
            break


if __name__ == '__main__':
    out_pipe, in_pipe = Pipe(True)
    son_p = Process(target=son_process, args=(100, (out_pipe, in_pipe)))
    son_p.start()

    # 等pipe被fork 后,关闭主进程的输出端
    # 这样,创建的Pipe一端连接着主进程的输入,一端连接着子进程的输出口
    out_pipe.close()
    for x in range(10):
        in_pipe.send(x)
    in_pipe.close()
    son_p.join()
    print("主进程也结束了")

#输出结果

0
1
2
3
4
5
6
7
8
9
主进程也结束了
  • 上面的代码中主要用到了pipe的send()、recv()、close()方法。当pipe的输入端被关闭,且无法接收到输入的值,那么就会抛出EOFError。
  • 新建一个Pipe(duplex)的时候,如果duplex为True,那么创建的管道是双向的;如果duplex为False,那么创建的管道是单向的。

multiprocessing.Queue

Queue据官方文档也是基于pipe的实现。
Queue的使用主要是一边put(),一边get().但是Queue可以是多个Process 进行put操作,也可以是多个Process进行get()操作。

  • 实例代码
from multiprocessing import Queue
from multiprocessing import    Process
import time
def f1(q):
    for i in range(10):
        print('f1 送福利啦! %s'%i)
        q.put(i)
        time.sleep(0.5)
def f2(q):
    while 1:
        print('f2收福利啦!%s'%q.get())
        time.sleep(0.5)
if __name__ == "__main__":
    q = Queue()
    p1 = Process(target=f1,args=(q,))
    p2 = Process(target=f2,args=(q,))
    p1.start()
    p2.start()
    p1.join()
    time.sleep(2)
    p2.terminate()

#输出
f1 送福利啦! 0
f2收福利啦!0
f1 送福利啦! 1
f2收福利啦!1
f1 送福利啦! 2
f2收福利啦!2
f1 送福利啦! 3
f2收福利啦!3
f1 送福利啦! 4
f2收福利啦!4
f1 送福利啦! 5
f2收福利啦!5
f1 送福利啦! 6
f2收福利啦!6
f1 送福利啦! 7
f2收福利啦!7
f1 送福利啦! 8
f2收福利啦!8
f1 送福利啦! 9
f2收福利啦!9

celery的使用

  • Celery 是一个由 Python 编写的简单、灵活、可靠的用来处理大量信息的分布式系统,它同时提供操作和维护分布式系统所需的工具。

  • Brokers
    brokers 中文意思为中间人,在这里就是指任务队列本身,Celery 扮演生产者和消费者的角色,brokers 就是生产者和消费者存放/拿取产品的地方(队列)
    常见的 brokers 有 rabbitmq、redis、Zookeeper 等

  • Result Stores / backend
    顾名思义就是结果储存的地方,队列中的任务运行完后的结果或者状态需要被任务发送者知道,那么就需要一个地方储存这些结果,就是 Result Stores 了
    常见的 backend 有 redis、Memcached 甚至常用的数据都可以。
  • Workers
    就是 Celery 中的工作者,类似与生产/消费模型中的消费者,其从队列中取出任务并执行
  • Tasks
    就是我们想在队列中进行的任务咯,一般由用户、触发器或其他操作将任务入队,然后交由 workers 进行处理。
    理解以上概念后我们就可以快速实现一个队列的操作:
    这里我们用 redis 当做 celery 的 broker 和 backend。

  • 首先在虚拟机上安装redis和celery

pip3 install redis
pip3 install celery

编写tasks.py代码
#tasks.py
from celery import Celery

app = Celery('tasks',  backend='redis://localhost:6379/0', broker='redis://localhost:6379/0') #配置好celery的backend和broker

@app.task  #普通函数装饰为 celery task
def add(x, y):
    return x + y


在tasks目录执行 celeryc  -A tasks worker --loglevel=info
意思就是运行 tasks 这个任务集合的 worker 进行工作(当然此时broker中还没有任务,worker此时相当于待命状态)
  • 拷贝tasks.py文件到本地目录
from tasks import add
result = add.delay(4, 4) #不要直接 add(4, 4),这里需要用 celery 提供的接口 delay 进行调用
while not result.ready():
    time.sleep(1)
print('task done: {0}'.format(result.get())

#输出
task done: 8

查看后台日志
[2018-05-26 06:56:59,880: INFO/ForkPoolWorker-1] Task tasks.add[6d79257d-f6bb-47ab-9992-48e358beae04] succeeded in 0.0012465869995139656s: 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值