python进程池 函数执行完后不退出_进程池

本文介绍了Python进程池的使用,包括创建进程池的异步与同步方式。异步方式允许主进程在子进程执行时继续运行,而同步方式会阻塞主进程,等待子进程结果。通过对比,突显了异步执行在处理大量任务时的优势。

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

19112f68aa2ecd3545dcc402443198da.png
10305

进程池

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间.

当被操作对象数目不大时,可以直接利用multiprocessing.Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效

Pool可以提供指定数量的进程,供用户调用.当有新的请求提交到pool中时,如果进程池还没有满,那么就会创建一个新的进程用来执行该请求, 但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束.才会创建新的进程来它

multiprocessing.Pool() 类有以下方法:

函数解释
apply_async(func[,args[,kwargs[,callback]]])不阻塞主进程,但是callback阻塞调用它的进程,异步操作
apply(func[,args[,kwargs]])使用阻塞的方式调用func
close()关闭pool, 使其不在接收新的任务
terninate()不管任务是否完成,立即终止
join()主进程阻塞,等待子进程的退出,必须在close\ terminate 之后使用

apply(func[,args[,kwargs[,callback[,error_callback]]]]): 返回一个结果对象,首先这是一个异步操作,如果指定了callback ,它必须是一个接受单个参数的可调用对象.当执行成功后,ballback 会被用与处理执行后的执行结果,否则调用error_callback ,如果指定了error_callback ,它必须是一个接受单个参数的可调用对象,当目标函数执行失败后,会将抛出的异常传递给error_callback处理.回调函数应该立即执行完成,否则会阻塞负责处理结果的线程或进程.

1.创建进程池

apply_async()  使用非阻塞异步的方式创建进程池:

  • 非阻塞指的是不会阻塞主进程
  • 异步指的是主进程不用等待调用结果,可以运行主进程中其他代码,等待子进程信号的回馈.
import multiprocessing,time


# 异步非阻塞的

def worker1():
    print('子进程:{},开始于:{}'.format(multiprocessing.current_process().name, time.time()))
    i = 0
    for j in range(10000):
        i = i+j
    print('子进程:{},结束于:{}'.format(multiprocessing.current_process().name, time.time()))
    return i


if __name__ == '__main__':
    """主进程"""
    print('主进程,开始于:{}'.format(time.time()))
    pool = multiprocessing.Pool(2)
    for i in range(4):
        pool.apply_async(worker1) # 异步
    print('-------------------')
    print('这是主进程在子进程后执行的部分:{}'.format(time.time()))
    print('-------------------')
    pool.close()
    pool.join()
    print('主进程结束:{}'.format(time.time()))

处理结果:

主进程,开始于:1572770657.2222323
-------------------
这是主进程在子进程后执行的部分:1572770657.2364972
-------------------
子进程:ForkPoolWorker-1,开始于:1572770657.2367756
子进程:ForkPoolWorker-2,开始于:1572770657.2368524
子进程:ForkPoolWorker-2,结束于:1572770657.2377691
子进程:ForkPoolWorker-2,开始于:1572770657.23802
子进程:ForkPoolWorker-1,结束于:1572770657.2383952
子进程:ForkPoolWorker-1,开始于:1572770657.2386503
子进程:ForkPoolWorker-2,结束于:1572770657.2388988
子进程:ForkPoolWorker-1,结束于:1572770657.240224
主进程结束:1572770657.3381264

apply() 使用阻塞同步创建进程池:

  • 阻塞是指只有一个进程处理完后,另外一个进程才会处理
  • 同步指的是,主进程必须等待返回的结果,只有当结果返回后才会执行主程序
import multiprocessing,time

def worker1():
    print('子进程:{},开始于:{}'.format(multiprocessing.current_process().name, time.time()))
    i = 0
    for j in range(10000):
        i = i+j
    print('子进程:{},结束于:{}'.format(multiprocessing.current_process().name, time.time()))
    return i

if __name__ == '__main__':
    """主进程"""
    print('主进程,开始于:{}'.format(time.time()))
    pool = multiprocessing.Pool(2)
    for i in range(4):
        pool.apply(worker1) # 同步
    print('-------------------')
    print('这是主进程在子进程后执行的部分:{}'.format(time.time()))
    print('-------------------')
    pool.close()
    pool.join()
    print('主进程结束:{}'.format(time.time()))

处理结果:

主进程,开始于:1572770654.673824
子进程:ForkPoolWorker-1,开始于:1572770654.687851
子进程:ForkPoolWorker-1,结束于:1572770654.688698
子进程:ForkPoolWorker-2,开始于:1572770654.6891456
子进程:ForkPoolWorker-2,结束于:1572770654.6897376
子进程:ForkPoolWorker-1,开始于:1572770654.6900878
子进程:ForkPoolWorker-1,结束于:1572770654.6906323
子进程:ForkPoolWorker-2,开始于:1572770654.6908329
子进程:ForkPoolWorker-2,结束于:1572770654.691444
-------------------
这是主进程在子进程后执行的部分:1572770654.691627
-------------------
主进程结束:1572770654.7890923

对比两个返回结果.注意主程序在子程序之后运行的部分这句话: 这体现了异步的好处,主进程可以不用等待子进程而自己运行代码.

对比两个返回结果,阻塞的程序必须一个一个的运行,因为阻塞了主程序,导致新的子程序不能生成,而不阻塞,则可以产生并行更多的子程序.

2.进程池调用Queue 队列

import multiprocessing

def worker1(queue):
 for i in range(10):
     queue.put('worker1:{}'.format(i))

def worker2(queue):
 for i in range(10, 20):
     queue.put('worker2:{}'.format(i))

def consumer(queue):
 print(queue.qsize())
 for i in range(queue.qsize()):
     ret = queue.get_nowait()
     print(ret)

if __name__ == '__main__':
 queue = multiprocessing.Manager().Queue()
 pool1 = multiprocessing.Pool(2)
 pool1.apply(worker1, (queue, ))
 pool1.apply(worker2, (queue, ))
 pool2 = multiprocessing.Pool(2)
 pool2.apply(consumer, (queue, ))
 pool1.close()
 pool1.join()
 pool2.close()
 pool2.join()

可以生成2个进程池,一个用来管理Queue 中的写入,一个用来管理读取

- END -
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值