进程池Pool结合Manager中的Queue队列的使用

本文详细介绍了如何在Python中使用multiprocessing模块的Pool进行并发任务处理,并探讨了如何通过Manager中的Queue实现进程间通信。实例演示了创建进程池、非阻塞任务调度和使用Queue进行数据传递的过程。
摘要由CSDN通过智能技术生成

目录

一.multiprocessing模块中进程池Pool的使用:

        from multiprocessing import Pool

        pool = Pool(进程池中的进程数)

        pool.apply_async(func=任务函数,args(元组类参数,))

        pool.close()

        pool.join()

二.进程池中的进程间通信问题:

        进程池Pool结合Manager中Queue的使用:

        from multiprocessing import Pool

        pool = Pool(进程池中的进程数)

        q = Manager().Queue()  # 使用Manager中的Queue

        pool.apply_async(func=任务函数,args(q,))

        pool.close()

        pool.join()

扩展:线程池的使用


进程池Pool:

        当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程,但如果是成百上千的进程目标,手动创建的工作量将非常巨大,此时可用到multiprocessing模块中的Pool类。

        初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果进程池还没有满,那么就会创建一个新的进程用来执行该请求;如果池中的进程数已经达到指定的最大值,那么该请求就会等待,知道池中有进程结束,才会用之前结束的进程来执行新的任务。

Pool常用方法:

        apply_async(func[,args[,kwds]]):使用非阻塞方式调用func(并行执行,阻塞方式必须等待上

                   一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给

                   func的关键字擦数列表。 

        close():关闭Pool,使其不再接收新的任务。

        terminate():不管任务是否完成,立即终止。

        join():主进程阻塞,等待子进程退出,必须在close()或terminate()之后使用。

一.multiprocessing模块中进程池Pool的使用:

        from multiprocessing import Pool

        pool = Pool(进程池中的进程数)

        pool.apply_async(func=任务函数,args(元组类参数,))

        pool.close()

        pool.join()

from multiprocessing import Pool
import os, time, random


def work1(msg):
    start_time = time.time()  # 开始时间
    print("循环任务%d由进程号%d进程执行" % (msg, os.getpid()))
    time.sleep(random.random())  # 随机生产0-1的浮点数
    end_time = time.time()  # 结束时间
    print(msg, "执行完毕,耗时%0.2f" % (end_time - start_time))


if __name__ == '__main__':
    pool = Pool(3)  # 定义一个进程池,最大进程数为3
    for i in range(1, 11):
        # 每次循环都会用空闲出来的子进程去调用目标任务(函数)
        pool.apply_async(func=work1, args=(i,))  
    print("------start------")
    pool.close()  # 关闭进程池,关闭后pool不再接收新的请求任务
    pool.join()  # 等待pool进程池中所有的子进程执行完成,必须放在pool.close()之后
    print("-----end------")


输出:
------start------
循环任务1由进程号18809进程执行
循环任务2由进程号18810进程执行
循环任务3由进程号18811进程执行
3 执行完毕,耗时0.42
循环任务4由进程号18811进程执行
1 执行完毕,耗时0.47
循环任务5由进程号18809进程执行
2 执行完毕,耗时0.54
循环任务6由进程号18810进程执行
4 执行完毕,耗时0.19
循环任务7由进程号18811进程执行
7 执行完毕,耗时0.06
循环任务8由进程号18811进程执行
8 执行完毕,耗时0.12
循环任务9由进程号18811进程执行
5 执行完毕,耗时0.82
循环任务10由进程号18809进程执行
6 执行完毕,耗时0.86
9 执行完毕,耗时0.85
10 执行完毕,耗时0.65
-----end------

总结:进程池中的3个进程,在循环执行任务时,初始时3个进程会同时启动并执行任务1,2,3;当进程18811率先执行完毕任务1时,会紧接着执行任务4。

_____________________________________________________________________________

二.进程池中的进程间通信问题:

        进程池Pool结合Manager中Queue的使用:

        from multiprocessing import Pool

        pool = Pool(进程池中的进程数)

        q = Manager().Queue()  # 使用Manager中的Queue

        pool.apply_async(func=任务函数,args(q,))

        pool.close()

        pool.join()

进程池中的Queue:如果要使用Pool创建进程,就需要使用到multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()。

from multiprocessing import Pool, Manager
import os, time, random


def reader(q):
    print("reader启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    print("reader进程%s从Queue中获取到的信息为:%s" % (os.getpid(), q.get()))


def writer(q):
    print("writer启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    for i in range(1, 11):
        q.put(i)


if __name__ == '__main__':
    print("(%s) start" % os.getpid())  # 打印主进程(父进程)
    pool = Pool(5)  # 创建进程池
    q = Manager().Queue()  # 使用Manager中的Queue
    pool.apply_async(func=writer, args=(q,))
    time.sleep(1)  # 先让writer任务完队列中生产数据,然后再用reader任务从队列中消费数据。
    while True:
        if q.qsize() > 0:
            pool.apply_async(func=reader, args=(q,))
        else:
            break
    pool.close()
    pool.join()

输出:
(23003) start
writer启动(23005),父进程为(23003)
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:1
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:2
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:3
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:4
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:5
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:6
reader启动(23006),父进程为(23003)
reader启动(23007),父进程为(23003)
reader启动(23009),父进程为(23003)
reader进程23006从Queue中获取到的信息为:7
reader启动(23008),父进程为(23003)
reader进程23007从Queue中获取到的信息为:8
reader进程23009从Queue中获取到的信息为:9
reader启动(23005),父进程为(23003)
reader进程23005从Queue中获取到的信息为:10
reader启动(23007),父进程为(23003)
reader启动(23009),父进程为(23003)
reader启动(23006),父进程为(23003)
reader启动(23005),父进程为(23003)

总结:进程池中的5个进程,根据Manager.Queue()队列中的数据,被动态分配给writer和reader任务,进程23005~23009共计5个进程,都轮流执行了reader任务。

扩展:线程池的使用

pool = threadpool.ThreadPool(num_workers=5)  # 定义了一个线程池
        # 调用makeRequests创建了要开启多线程的函数
requests = threadpool.makeRequests(some_callable, list_of_args, callback)
        # 将所有要运行多线程的请求扔进线程池
[pool.putRequest(req) for req in requests]
        # 等待所有的线程完成工作后退出。
pool.wait()
import time

import threadpool


def work(max):
    for i in max:
        print(i)
        time.sleep(1)


if __name__ == '__main__':
    pool = threadpool.ThreadPool(num_workers=5)
    max_list = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
    s_time = time.time()
    requests = threadpool.makeRequests(work, max_list)
    [pool.putRequest(req) for req in requests]
    pool.wait()
    e_time = time.time()
    print("耗时:{}".format(e_time - s_time))

输出:
1
2
3
4
5
6
7
8
9
耗时:2.010507822036743

### 回答1: 在 Python ,可以使用 `multiprocessing` 库的 `Queue` 类来在进程传递信息。 首先,在主进程创建一个 `Queue` 对象,然后将该对象作为参数传递给进程的每个进程: ```python from multiprocessing import Queue, Process def worker(queue): # 从队列获取信息 message = queue.get() # 处理信息 print(message) if __name__ == '__main__': # 创建一个队列 queue = Queue() # 创建进程,并将队列作为参数传递给每个进程 with Process(target=worker, args=(queue,)) as process: # 向队列添加信息 queue.put('Hello, World!') # 等待进程完成 process.join() ``` 在进程的每个进程,可以使用 `Queue.get()` 方法从队列获取信息,并使用 `Queue.put()` 方法向队列添加信息。 注意,在使用进程队列时,应该使用 `multiprocessing` 库进程队列,而不是 `threading` 库的线程和队列。 ### 回答2: 在Python使用进程时,可以使用队列来传递信息。 首先,需要导入`multiprocessing`模块的`Pool`和`Queue`。 使用`Pool`创建进程对象,可以指定进程数。然后,使用`Queue`创建一个队列对象,用于在进程之间传递信息。 在主进程,将需要传递的信息通过`put`方法放入队列。 在子进程使用`get`方法从队列取出信息。 下面是一个示例代码: ```python from multiprocessing import Pool, Queue def worker(queue): data = queue.get() # 从队列取出信息 # 进行子进程的操作 if __name__ == '__main__': pool = Pool(processes=4) # 创建进程,指定进程数为4 queue = Queue() # 创建队列对象 for i in range(10): queue.put(i) # 向队列放入信息 pool.apply_async(worker, (queue,)) # 在进程异步执行worker函数 pool.close() # 关闭进程 pool.join() # 等待所有子进程结束 ``` 在上面的示例代码,创建了一个进程对象`pool`,队列对象`queue`以及放入队列的信息。 然后,通过`apply_async`方法在进程异步执行`worker`函数,并将队列作为参数传递给子进程。 子进程使用`get`方法从队列取出信息。 最后,关闭进程并等待所有子进程结束。 这样,就可以在Python使用队列进程传递信息了。 ### 回答3: 在Python,在进程使用队列进行信息传递的方法如下: 首先,需要导入`multiprocessing`模块的`Pool`类和`Queue`类: ```python from multiprocessing import Pool, Queue ``` 然后,创建一个共享队列对象: ```python queue = Queue() ``` 接下来,在进程的任务函数,通过将队列作为参数传递给进程的函数,在不同的进程之间进行信息传递: ```python def task_function(queue): # 在进程需要传递的信息 message = "Hello from process {}".format(os.getpid()) # 将信息放入队列 queue.put(message) # 创建进程 pool = Pool() # 向进程添加任务 pool.apply_async(task_function, args=(queue,)) # 关闭进程 pool.close() # 等待所有任务完成 pool.join() ``` 在上述代码,我们调用了`apply_async`方法向进程添加任务,并将队列作为参数传递给任务函数`task_function`。然后,我们关闭进程,并使用`join`方法等待所有任务的完成。 最后,可以通过在主进程队列获取数据来获得在进程传递的信息: ```python while not queue.empty(): message = queue.get() print(message) ``` 上述代码的`queue.empty()`方法用于判断队列是否为空,`queue.get()`方法用于从队列获取数据。 通过以上步骤,就可以在Python进程使用队列进行信息传递了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chuntian_tester

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值