Python-- concurrent包(异步并行任务编程模块)

concurrent.futures

3.2版本引入的模块

  • 异步并行任务编程模块,提供一个高级的异步可执行的便利接口
  • 提供了2个池执行器
    ThreadPoolExecutor 异步调用的线程池的Executor
    ProcessPoolExecutor 异步调用的进程池的Executor

ThreadPoolExecutor对象

首先需要定义一个池的执行器对象,Executor类子类对象

方法含义
ThreadPoolExecutor(max_workers=1)池中至多创建max_workers个线程的池来同时异步执行,返回 Executor实例
submit(fn, *args, **kwargs)提交执行的函数及其参数,返回Future类的实例
shutdown(wait=True清理池

Future类

方法含义
done()如果调用被成功的取消或者执行完成,返回True
cancelled()如果调用被成功的取消,返回True
running()如果正在运行且不能被取消,返回True
cancel()尝试取消调用。如果已经执行且不能取消返回False,否则返回True
result(timeout=None)取返回的结果,timeout为None,一直等待返回;timeout设置到期,抛出concurrent.futures.TimeoutError 异常
exception(timeout=None)取返回的异常,timeout为None,一直等待返回;timeout设置到期,抛出concurrent.futures.TimeoutError 异常

ThreadPoolExecutor例子

import threading
from concurrent import futures
import logging
import time

# 输出格式定义
FORMAT = '%(asctime)-15s\t [%(processName)s:%(threadName)s, ' \
         '%(process)d:%(thread)8d] %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)

def worker(n):
    logging.info('begin to work-{}'.format(n))
    time.sleep(5)
    logging.info('finished {}'.format(n))

# 创建线程池,池容量为3
executer = futures.ThreadPoolExecutor(max_workers=3)
fs = []
for i in range(3):
    future = executer.submit(worker, i)
    fs.append(future)

for i in range(3, 6):
    future = executer.submit(worker, i)
    fs.append(future)

while True:
    time.sleep(2)
    logging.info(threading.enumerate())

    flag = True
    for f in fs: # 判断是否还有未完成的任务
        logging.info(f.done())
        flag = flag and f.done()
        # if not flag: # 注释了这个if,方便观看输出的日志
        #     break

    print('-' * 30)
    if flag:
        executer.shutdown()
        logging.info(threading.enumerate())
        break

线程池一旦创建了线程,就不需要频繁清除

  • 执行结果
2019-06-11 16:10:53,824	 [MainProcess:ThreadPoolExecutor-0_0, 341824:  341040] begin to work-0
2019-06-11 16:10:53,824	 [MainProcess:ThreadPoolExecutor-0_1, 341824:  341248] begin to work-1
2019-06-11 16:10:53,826	 [MainProcess:ThreadPoolExecutor-0_2, 341824:  335160] begin to work-2
2019-06-11 16:10:55,828	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>, <Thread(ThreadPoolExecutor-0_0, started daemon 341040)>, <Thread(ThreadPoolExecutor-0_1, started daemon 341248)>, <Thread(ThreadPoolExecutor-0_2, started daemon 335160)>]
2019-06-11 16:10:55,828	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:55,828	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:55,829	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:55,829	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:55,829	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:55,829	 [MainProcess:MainThread, 341824:  339368] False
------------------------------
------------------------------
2019-06-11 16:10:57,829	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>, <Thread(ThreadPoolExecutor-0_0, started daemon 341040)>, <Thread(ThreadPoolExecutor-0_1, started daemon 341248)>, <Thread(ThreadPoolExecutor-0_2, started daemon 335160)>]
2019-06-11 16:10:57,829	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:57,829	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:57,830	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:57,830	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:57,830	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:57,830	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:58,825	 [MainProcess:ThreadPoolExecutor-0_0, 341824:  341040] finished 0
2019-06-11 16:10:58,825	 [MainProcess:ThreadPoolExecutor-0_0, 341824:  341040] begin to work-3
2019-06-11 16:10:58,826	 [MainProcess:ThreadPoolExecutor-0_1, 341824:  341248] finished 1
2019-06-11 16:10:58,826	 [MainProcess:ThreadPoolExecutor-0_1, 341824:  341248] begin to work-4
2019-06-11 16:10:58,827	 [MainProcess:ThreadPoolExecutor-0_2, 341824:  335160] finished 2
2019-06-11 16:10:58,827	 [MainProcess:ThreadPoolExecutor-0_2, 341824:  335160] begin to work-5
2019-06-11 16:10:59,830	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>, <Thread(ThreadPoolExecutor-0_0, started daemon 341040)>, <Thread(ThreadPoolExecutor-0_1, started daemon 341248)>, <Thread(ThreadPoolExecutor-0_2, started daemon 335160)>]
2019-06-11 16:10:59,830	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:10:59,831	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:10:59,831	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:10:59,831	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:59,831	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:10:59,831	 [MainProcess:MainThread, 341824:  339368] False
------------------------------
------------------------------
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>, <Thread(ThreadPoolExecutor-0_0, started daemon 341040)>, <Thread(ThreadPoolExecutor-0_1, started daemon 341248)>, <Thread(ThreadPoolExecutor-0_2, started daemon 335160)>]
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:11:01,832	 [MainProcess:MainThread, 341824:  339368] False
2019-06-11 16:11:03,826	 [MainProcess:ThreadPoolExecutor-0_0, 341824:  341040] finished 3
2019-06-11 16:11:03,827	 [MainProcess:ThreadPoolExecutor-0_1, 341824:  341248] finished 4
2019-06-11 16:11:03,827	 [MainProcess:ThreadPoolExecutor-0_2, 341824:  335160] finished 5
------------------------------
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>, <Thread(ThreadPoolExecutor-0_0, started daemon 341040)>, <Thread(ThreadPoolExecutor-0_1, started daemon 341248)>, <Thread(ThreadPoolExecutor-0_2, started daemon 335160)>]
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,832	 [MainProcess:MainThread, 341824:  339368] True
2019-06-11 16:11:03,833	 [MainProcess:MainThread, 341824:  339368] [<_MainThread(MainThread, started 339368)>]

Process finished with exit code 0

ProcessPoolExecutor对象

  • 方法一样,就是使用多进程完成

ProcessPoolExecutor例子

import threading
from concurrent import futures
import logging
import time

# 输出格式定义
FORMAT = '%(asctime)-15s\t [%(processName)s:%(threadName)s, ' \
         '%(process)d:%(thread)8d] %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)

def worker(n):
    logging.info('begin to work-{}'.format(n))
    time.sleep(5)
    logging.info('finished {}'.format(n))

if __name__ == '__main__':
    # 创建进程池,池容量为3
    executer = futures.ProcessPoolExecutor(max_workers=3)
    fs = []
    for i in range(3):
        future = executer.submit(worker, i)
        fs.append(future)

    for i in range(3, 6):
        futuer = executer.submit(worker, i)
        fs.append(future)

    while True:
        time.sleep(2)
        logging.info(threading.enumerate())

        flag = True
        for f in fs: # 判断是否还有未完成的任务
            logging.info(f.done())
            flag = flag and f.done()
            # if not flag: # 注释了这个if,方便观看输出的日志
            #     break

        print('-' * 30)

        if flag:
            executer.shutdown() # 清理池。除非不用了,否则不要频繁清理池
            logging.info(threading.enumerate()) # 多进程时看主线程已经没有必要了
            break
  • 执行结果
2019-06-11 16:22:34,441	 [Process-2:MainThread, 343300:  343320] begin to work-0
2019-06-11 16:22:34,466	 [Process-1:MainThread, 343260:  343312] begin to work-1
2019-06-11 16:22:34,488	 [Process-3:MainThread, 343232:  343328] begin to work-2
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] [<_MainThread(MainThread, started 343220)>, <Thread(Thread-1, started daemon 343284)>, <Thread(QueueFeederThread, started daemon 343168)>]
------------------------------
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:36,201	 [MainProcess:MainThread, 343224:  343220] False
------------------------------
2019-06-11 16:22:38,201	 [MainProcess:MainThread, 343224:  343220] [<_MainThread(MainThread, started 343220)>, <Thread(Thread-1, started daemon 343284)>, <Thread(QueueFeederThread, started daemon 343168)>]
2019-06-11 16:22:38,201	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:38,202	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:38,202	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:38,202	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:38,202	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:38,202	 [MainProcess:MainThread, 343224:  343220] False
2019-06-11 16:22:39,442	 [Process-2:MainThread, 343300:  343320] finished 0
2019-06-11 16:22:39,442	 [Process-2:MainThread, 343300:  343320] begin to work-3
2019-06-11 16:22:39,467	 [Process-1:MainThread, 343260:  343312] finished 1
2019-06-11 16:22:39,467	 [Process-1:MainThread, 343260:  343312] begin to work-4
2019-06-11 16:22:39,488	 [Process-3:MainThread, 343232:  343328] finished 2
2019-06-11 16:22:39,488	 [Process-3:MainThread, 343232:  343328] begin to work-5
------------------------------
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] [<_MainThread(MainThread, started 343220)>, <Thread(Thread-1, started daemon 343284)>, <Thread(QueueFeederThread, started daemon 343168)>]
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:40,202	 [MainProcess:MainThread, 343224:  343220] True
2019-06-11 16:22:44,442	 [Process-2:MainThread, 343300:  343320] finished 3
2019-06-11 16:22:44,468	 [Process-1:MainThread, 343260:  343312] finished 4
2019-06-11 16:22:44,488	 [Process-3:MainThread, 343232:  343328] finished 5
2019-06-11 16:22:44,511	 [MainProcess:MainThread, 343224:  343220] [<_MainThread(MainThread, started 343220)>]

Process finished with exit code 0

支持上下文管理

  • concurrent.futures.ProcessPoolExecutor继承自concurrent.futures._base.Executor,而父类有__enter____exit__方法,支持上下文管理。可以使用with语句
  • __exit__方法本质还是调用的shutdown(wait=True),就是一直阻塞到所有运行的任务完成

使用方法

with ThreadPoolExecutor(max_workers=1) as executor:
	future = executor.submit(pow, 323, 1235)
	print(future.result())
  • 使用上下文改造上面的例子,增加返回计算的结果

ProcessPoolExecutor 上下文例子

import threading
from concurrent import futures
import logging
import time

# 输出格式定义
FORMAT = '%(asctime)-15s\t [%(processName)s:%(threadName)s, ' \
         '%(process)d:%(thread)8d] %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)

def worker(n):
    logging.info('begin to work-{}'.format(n))
    time.sleep(5)
    logging.info('finished {}'.format(n))

if __name__ == '__main__':
    # 创建进程池,池容量为3
    executer = futures.ProcessPoolExecutor(max_workers=3)

    with executer: # 上下文管理
        fs = []
        for i in range(3):
            future = executer.submit(worker, i)
            fs.append(future)

        for i in range(3, 6):
            futuer = executer.submit(worker, i)
            fs.append(future)

        while True:
            time.sleep(2)
            logging.info(threading.enumerate())

            flag = True
            for f in fs: # 判断是否还有未完成的任务
                logging.info(f.done())
                flag = flag and f.done()
                # if not flag: # 注释了这个if,方便观看输出的日志
                #     break

            print('-' * 30)

            if flag:
                break
        # executer.shutdown() # 上下文清理了资源
    logging.info('===end===')
    logging.info(threading.enumerate()) # 多进程时看主线程已经没有必要了
  • 执行结果
2019-06-11 16:48:06,023	 [Process-2:MainThread, 344928:  346108] begin to work-0
2019-06-11 16:48:06,040	 [Process-1:MainThread, 342556:  343704] begin to work-1
2019-06-11 16:48:06,044	 [Process-3:MainThread, 334452:  344428] begin to work-2
2019-06-11 16:48:07,761	 [MainProcess:MainThread, 346100:  346096] [<_MainThread(MainThread, started 346096)>, <Thread(Thread-1, started daemon 342024)>, <Thread(QueueFeederThread, started daemon 343912)>]
2019-06-11 16:48:07,761	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:07,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:07,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:07,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:07,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:07,762	 [MainProcess:MainThread, 346100:  346096] False
------------------------------
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] [<_MainThread(MainThread, started 346096)>, <Thread(Thread-1, started daemon 342024)>, <Thread(QueueFeederThread, started daemon 343912)>]
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:09,762	 [MainProcess:MainThread, 346100:  346096] False
2019-06-11 16:48:09,763	 [MainProcess:MainThread, 346100:  346096] False
------------------------------
2019-06-11 16:48:11,023	 [Process-2:MainThread, 344928:  346108] finished 0
2019-06-11 16:48:11,024	 [Process-2:MainThread, 344928:  346108] begin to work-3
2019-06-11 16:48:11,041	 [Process-1:MainThread, 342556:  343704] finished 1
2019-06-11 16:48:11,042	 [Process-1:MainThread, 342556:  343704] begin to work-4
2019-06-11 16:48:11,044	 [Process-3:MainThread, 334452:  344428] finished 2
2019-06-11 16:48:11,045	 [Process-3:MainThread, 334452:  344428] begin to work-5
------------------------------
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] [<_MainThread(MainThread, started 346096)>, <Thread(Thread-1, started daemon 342024)>, <Thread(QueueFeederThread, started daemon 343912)>]
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:11,763	 [MainProcess:MainThread, 346100:  346096] True
2019-06-11 16:48:16,024	 [Process-2:MainThread, 344928:  346108] finished 3
2019-06-11 16:48:16,042	 [Process-1:MainThread, 342556:  343704] finished 4
2019-06-11 16:48:16,045	 [Process-3:MainThread, 334452:  344428] finished 5
2019-06-11 16:48:16,077	 [MainProcess:MainThread, 346100:  346096] ===end===
2019-06-11 16:48:16,077	 [MainProcess:MainThread, 346100:  346096] [<_MainThread(MainThread, started 346096)>]

Process finished with exit code 0

总结

  • 该库统一了线程池、进程池调用,简化了编程。
  • 是Python简单的思想哲学的体现。
  • 唯一的缺点:无法设置线程名称。但这都不值一提。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值