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简单的思想哲学的体现。
- 唯一的缺点:无法设置线程名称。但这都不值一提。