python3的concurrent包

concurrent包

concurrent.futures

3.2版本引入的模块.

异步并行任务编程模块, 提供一个高级的一部可执行的便利接口.

提供两个池执行器
ThreadPoolExecutor 异步调用的线程池的Executor
ProcessPlloExecutor异步调用进程池的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异常
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()   #有一个未完成flag都会变成False
        if not flag:##出现一次就说明未完成, 提前结束
            break

    print("-" * 30)

    if flag:
        executer.shutdown()
        logging.info(threading.enumerate())
        break
   ## 线程一旦创建就不应该频繁被清除

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))

# 创建线程池, 容量为3
if __name__=='__main__':
    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):
    #     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()   #有一个未完成flag都会变成False
            if not flag:##出现一次就说明未完成, 提前结束
                break

        print("-" * 30)

        if flag:
            executer.shutdown()
            logging.info(threading.enumerate())
            break

和ThreadingPoolExecutor一样, 只是需要加上一句if __name__=="__main__":

支持上下文管理

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

使用方法

from concurrent import futures

with futures.ThreadPoolExecutor(max_workers=1) as executor:
    future = executor.submit(pow, 2, 3)
    print(future.result())  ##阻塞,等待返回结果

# futures.ThreadPoolExecutor.__enter__()
#     def __enter__(self):
#         return self
#     
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         self.shutdown(wait=True)
#         return False

改造之前的例子

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
if __name__=='__main__':
    fs = []
    with  futures.ProcessPoolExecutor(max_workers=3) as executer:
        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()   #有一个未完成flag都会变成False
                if not flag:##出现一次就说明未完成, 提前结束
                    break

            print("-" * 30)

            if flag:
                logging.info(threading.enumerate())
                break

总结

该库统一了线程池,进程池调用,简化了编程.
是Python简单的思想哲学的体现.

唯一的缺点:无法设置线程名称. 但是这都不值一提.

你可能感兴趣的:(python3的concurrent包)