测试之路

#Python#实现简单的并行编程

2018-06-30  本文已影响0人  我叫GTD
concurrent.futures库提供了一个ProcessPoolExecutor类,可用来在单独运行的Python解释器实例中执行计算密集型的函数。

下面是一个简单的脚本:

# -*- coding: utf-8 -*-
import time
from concurrent.futures import ProcessPoolExecutor


def sleepy(arg):
    print("I'm {}, I'm going to sleep.".format(arg))
    time.sleep(6.6)
    print("{} wake up!".format(arg))
    return str('{} recovery!'.format(arg))


if __name__ == '__main__':
    names = ['Jack', 'Anna', 'Tom', 'White', 'Paul']
    begin = time.time()
    with ProcessPoolExecutor() as pool:
        all_man = pool.map(sleepy, names)
    end = time.time()
    for each in all_man:
        print(each)
    print('\nAmazing Five wake up, it takes {:.2f} seconds'.format(end - begin))

实际的性能会根据机器上的CPU个数而有所不同。
在底层,ProcessPoolExecutor创建了N个独立运行的Python解释器,这里的N就是在系统上检测到的可用的CPU个数。可以修改创建的Python进程个数,只要给ProcessPoolExexutor(N)提供一个可选的参数即可。进程池会一直运行,直到with语句块中的最后一条语句执行完毕为止,此时进程池就会关闭。但是,程序会一直等待所有已经提交的任务都处理完毕为止。
提交到进程池中的任务必须定义成函数的形式。有两种方法可以提交任务。如果想并行处理一个列表推导式或者map()操作,可以使用pool.map()(如上例)。
还有一种方式就是可以通过pool.submit()方法来手动提交一个单独的任务:

def when_done(r):
    print('Got:', r.result())

with ProcessPoolExecutor() as pool1:
    for i in range(1,10):
        results = pool1.submit(sleepy, i)
        results.add_done_callback(when_done) # 提供一个回调函数,让它在任务完成时得到触发执行。

如果手动提交任务,得到的结果就是一个Future实例。要获取到实际的结果还需要调用它的result()方法。直接调用会阻塞进程,直到完成并将结果返回给进程池为止。
与其让进程阻塞,也可以提供一个回调函数,让它在任务完成时得到触发执行。如上例中的 results.add_done_callback(when_done)


要考虑的几个因素:

参考书籍:

Python Cookbook:12.8 Page 521 - 525

PS:

这本书终于快看完了,也不枉这三个月来同事午休的时间我端杯咖啡去公共区啃书。里面有些内容不好啃,也做了标注,回头再继续看看。看了这么多(全书共680页),不能说自己看了就全部都会了,不过也给自己一些启发。第14章-测试、调试以及异常对测试者来说是个重点,unittest.mock()模块书中讲的不多,但很强大,用Python编写单元测试脚本的话,这是个重要点。
千万不要只以为unittest就是组建个测试集,输出测试报告的框架,远比你想象的要强大的多。
哦,对了,这是第3版。

上一篇下一篇

猜你喜欢

热点阅读