关于ThreadPoolExecutor和ProcessPoolExecutor的用法

concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用

下面的例子,使用的sbumit方法调用。使用 add_done_callback 添加回调函数。
如果不使用回调函数,可以用 future.result() 获取返回的结果。一般2种方法用一种就可以了。

from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import ProcessPoolExecutor

## 定义回调函数
def callback (res):
    res = res.result()            ## 这里获取到的函数的返回值
    url = res['url']
    ...

## 定义处理函数
def parse_data(data):
    ...
	return {"":"","":""}

executor = ProcessPoolExecutor(max_workers=3)       ## 定义了最大并发量是 3  使用进程池
executor = ThreadPoolExecutor(max_workers=3)       ##  定义了最大并发量是 3  使用线程池

futures = []
for url in urls:
    future = executor.submit(parse_data, url).add_done_callback(callback)
    futures.append(future)                          ## futures 用于存放后面的执行结果,便于打印,如果不需要的话可以不写
for future in concurrent.futures.as_completed(futures):
    print(future.result())
    if future.exception():
      print(future.exception())
executor.shutdown(True)

## 也可以使用map的方法来做
futures = executor.map(parse_data, urls)
for future in futures:
    logging.info(future)

future.result() 是函数返回的返回值

如果是 IO 密集多尽量用多线程, CPU 密集尽量用多进程.
map 函数会比 submit 更简洁, 但是没法对返回一个一个处理, 而 submit 的好处是可以对每个返回在执行完成的瞬间处理, 不用等到每个线程/进程都执行完毕.
运用多进程/多线程的时候函数报错并不一定会直接结束程序, 而有可能会什么都不发生, 这样需要在 as_completed 之后捕捉异常, 用上面代码所示语句就可以.

网上找来的一段例子

def get_data(self, workers=5):
    self.cookie = self.get_cookie(self)

    total_data = {
        'data'       : [],
        'status_code': 0
    }

    with concurrent.futures.ProcessPoolExecutor(max_workers=workers) as executor:
        futures = [executor.submit(self.analyze, patent_number) for patent_number in self.patent_number_list]
        for future in concurrent.futures.as_completed(futures):
            # add result to total data
            total_data['data'].append(future.result())

    return total_data

你可能感兴趣的:(关于ThreadPoolExecutor和ProcessPoolExecutor的用法)