python开启多进程(使用进程池multiprocessing.Pool)

一、摘要

python和java、C++不一样,java一般在进行多项耗时计算时常采用多线程,而python则更适合采用多进程。关于线程和进程的区别,这里不作详细解释。这里介绍一种python开启多进程的方法,使用multiprocessing.Pool进程池。

 

二、示例

import traceback
from multiprocessing import Pool
import time

def work(province, arr):
    #在这里进行复杂或耗时的计算
    time.sleep(10)
    print(arr)
    print(time.strftime("%Y-%m-%d %H:%M:%S"), "finish....", province)
    arr.append("新数据:" + province)
    return arr

def workMulti(province, arr):
    try:
        work(province, arr)
    except Exception as e:
        print('Error: %s' % (province), traceback.print_exc())

if __name__ == '__main__':
    provinces = ["北京市", "天津市", "上海市", "重庆市", "河北省",
                "河南省", "云南省", "辽宁省", "黑龙江省", "湖南省",
                "广西壮族自治区", "广东省", "海南省"]
    arr=["原数据"]
    po = Pool(processes=5) #允许开几个进程
    for province in provinces:
        print("Add task:", province)
        # 开启进程运行workMulti函数,传入参数province,arr。
        # 注意最后一个逗号是必须的,不是多余的
        po.apply_async(workMulti, args=(province,arr,))
    print("AAA****************************")
    po.close() #关闭进程池入口,此后不能再向进程池中添加任务了
    print("BBB****************************")
    po.join() #阻塞等待,只有进程池中所有任务都完成了才往下执行
    print("CCC****************************")

这里开启多进程去简单打印省份,实际应用中只需把复杂或耗时的计算放到work中即可。运行结果如下:

 

三、注意事项及建议

1、关于进程的开启代码一定要放在if __name__ == '__main__':代码之下,不能放到函数中或其他地方。

2、po.apply_async(workMulti, args=(province,arr,))开启进程调用workMulti,需要几个参数传几个,最后需要加一个逗号,因为其传递的参数是tuple类型。

3、进程之间的参数变量是不共享的, 在某个进程中修改其函数参数, 在其他进程中是不可见的。这里每次打印的都是['原数据']足以说明。

4、进程池接受任务并非阻塞式。这里进程池虽然只开5个,但它可以一次性接受很多任务, 任务的执行由进程池Pool自行安排,这里打印的Add task是连续的,并不需要等待进程池有空进程。

5、这里为何要调用workMulti而不直接调用work?

答:假如work函数中报错,你会发现程序看起来运行正常,你将发现不了错误。通过在workMulti中加入try:...except:...以及traceback.print_exc(),我们可以打印出进程运行的异常。

6、多进程如何接收计算结果?

答:方法1:使用callback回调方法,我没使用过,不详细说明

       方法2:在进程中把计算结果保存下来,如保存到数据库或文件,所有进程计算结束后再提取。我多采用这种方法,这种方法在部分进程计算失败后仍然能保留计算成功的那些结果。

7、开启多少个进程合适?

答:看你跑的是什么类型的任务。如果是计算密集型(耗CPU的),建议开启和CPU核心线程数一样的进程,如果同时你还要操作计算机或进行其他任务,那最好再留出一点CPU,不然将会卡死。如果是耗时型(不耗CPU,如网络请求等),可以考虑开多一些进程,不需要考虑CPU核心线程数。

 

 

author:蓝何忠

email:lanhezhong@163.com

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Pythonmultiprocessing.Pool模块和multiprocessing.dummy.Pool模块都是用于创建进程和线程的工具。 进程(multiprocessing.Pool)是一组维护在进程中的工作者,它们可以并行地执行任务。该模块是基于multiprocessing模块实现的,它通过创建多个进程来并行执行任务。 下面是一个创建进程的示例: ``` python import multiprocessing def worker(process_num): print("Process %d is working" % process_num) if __name__ == '__main__': pool = multiprocessing.Pool(processes=4) for i in range(5): pool.apply_async(worker, args=(i,)) pool.close() pool.join() ``` 上面的示例中,我们创建了一个包含4个进程进程,并向进程中提交了5个任务,每个任务调用worker函数并传递一个进程编号作为参数。我们使用apply_async方法向进程中提交任务,并使用close和join方法管理进程。 线程(multiprocessing.dummy.Pool)是一组维护在线程中的工作者,它们可以并行地执行任务。该模块是基于threading模块实现的,它通过创建多个线程来并行执行任务。 下面是一个创建线程的示例: ``` python from multiprocessing.dummy import Pool import time def worker(thread_num): print("Thread %d is working" % thread_num) time.sleep(1) if __name__ == '__main__': pool = Pool(4) for i in range(5): pool.apply_async(worker, args=(i,)) pool.close() pool.join() ``` 上面的示例中,我们创建了一个包含4个线程的线程,并向线程中提交了5个任务,每个任务调用worker函数并传递一个线程编号作为参数。我们使用apply_async方法向线程中提交任务,并使用close和join方法管理线程。 需要注意的是,线程进程的用法基本相同,但是由于线程在Python中不能真正地并行执行,因此线程的性能可能比进程差。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值