Queue消息队列和Pool进程池

Queue消息队列

在python中,多个进程之间是无法共享全局变量的。但有时候我们又必须使用同一些数据。这时候就可以利用消息队列来实现。
Queue消息队列就相当于一个管道,数据从一头进,另一头出。
示例程序:

import multiprocessing
import time

# 创建消息队列,用来储存数据
q = multiprocessing.Queue()


def put_in():
    for i in range(10):
        q.put(i)
        print(i, '  put in')
        time.sleep(0.1)
        
        
def get_out():
    for _ in range(10):
        print(q.get(), '  get out')


pp = multiprocessing.Process(target=put_in)

gp = multiprocessing.Process(target=get_out)


pp.start()
gp.start()

运行结果:

0   put in
0   get out
1   put in
1   get out
2   put in
2   get out
3   put in
3   get out
4   put in
4   get out
5   put in
5   get out
6   put in
6   get out
7   put in
7   get out
8   put in
8   get out
9   put in
9   get out

Queue常见方法

  • Queue.qsize():返回当前队列包含的消息数量;
  • Queue.empty():如果队列为空,返回True,反之False ;
  • Queue.full():如果队列满了,返回True,反之False;
  • Queue.get():获取队列中的一条消息,然后将其从列队中移除,可传参超时时长。
  • Queue.get_nowait():相当Queue.get(False),取不到值时触发异常:Empty;
  • Queue.put():将一个值添加进数列,可传参超时时长。
  • Queue.put_nowait():相当于Queue.get(False),当队列满了时报错:Full

其中,Queue.empty()方法不可靠,容易出现错误判断,与代码运行速度有关,因此可以用Queue.qsize()来判断队列是否为空。

Pool进程池

在你需要多进程的时候,又或是你不清楚需要多少进程合适的时候。我们可以利用进程池来协助创建进程。
进程池的创建需要调用multiprocessing.Pool(5)方法,其中括号里传递的参数是最大可创建进程数量。如果没有传参,默认无限量。
进程池创建并调用进程代码如下:

import multiprocessing
import time


# 拷贝任务
def work():
    print("复制中...", multiprocessing.current_process().pid)
    time.sleep(0.5)

if __name__ == '__main__':
    # 创建进程池
    # 3:进程池中进程的最大个数
    pool = multiprocessing.Pool(3)
    # 模拟大批量的任务,让进程池去执行
    for i in range(5):
        # 循环让进程池执行对应的work任务
        # 同步执行任务,一个任务执行完成以后另外一个任务才能执行
        pool.apply(work)

创建进程池后,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
另外,在执行进程时候,选择pool.apply()方法表示的是同步进程池。而我们一般用pool.apply_async(),这叫做异步进程池。在使用异步进程池的时候,我们应该在最后记得关闭进程池,用来告诉主进程不会再有更多的进程进来。另外还要加上进程池进程等待。让主进程等待所有进程池进程运行完之后再退出。
示例代码:

# 进程池:池子里面放的进程,进程池会根据任务执行情况自动创建进程,而且尽量少创建进程,合理利用进程池中的进程完成多任务
import multiprocessing
import time


# 拷贝任务
def work():
    print("复制中...", multiprocessing.current_process().pid)
    # 获取当前进程的守护状态
    # 提示:使用进程池创建的进程是守护主进程的状态,默认自己通过Process创建的进程是不是守住主进程的状态
    # print(multiprocessing.current_process().daemon)
    time.sleep(0.5)

if __name__ == '__main__':
    # 创建进程池
    # 3:进程池中进程的最大个数
    pool = multiprocessing.Pool(3)
    # 模拟大批量的任务,让进程池去执行
    for i in range(5):
        # 循环让进程池执行对应的work任务
        # 同步执行任务,一个任务执行完成以后另外一个任务才能执行
        # pool.apply(work)
        # 异步执行,任务执行不会等待,多个任务一起执行
        pool.apply_async(work)

    # 关闭进程池,意思告诉主进程以后不会有新的任务添加进来
    pool.close()
    # 主进程等待进程池执行完成以后程序再退出
    pool.join()

猜你喜欢

转载自blog.csdn.net/washing1127/article/details/83448529
今日推荐