进程池与线程池-concurrent.futures

concurrent.futures提供了线程池ThreadPoolExecutor、进程池ProcessPoolExecutor接口。

concurrent.futures.Executor

Executor是一个抽象类,ThreadPoolExecutor和ProcessPoolExecutor是Executor的子类。

  1. submit(fn,/,*args,**kwargs)
    • 提交一个任务,返回一个Future对象表示任务的结果
    • fn可调用对象,args 和kwargs是fn的参数
  2. map(func, *iterables, timeout=None, chunksize=1)
    • 创建一个map任务,返回一个迭代器。
    • 当使用ProcessPoolExecutor时,这个方法会将iterable切分为几块,分为多个任务提交的进程池
    • 线程池不会拆分任务
  3. shutdown(wait=True, *, cancel_futures=False)
    • 任务运行完成后释放资源。如果在shutdown后调用map或submit会引起RuntimeError
    • wait如果为True(默认)会阻塞直到任务运行完成并释放资源。如果为False则会立即返回,但是executor也会在任务运行完成后释放资源。无论是T or F,python程序不会在任务运行完成并释放资源后退出。
    • cancel_futures如果为True,则会取消没有开始执行的任务。无论是True还是False都不会取消正在运行或已完成的任务。

Executor是实现了上下文协议的,可以使用with语句避免使用shutdown

with ThreadPoolExecutor(max_workers=4) as e:
    pass 

concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

- 线程池
- max_workers如果为空则工作线程数为5(3.5)
- max_workers的默认值为min(32, os.cpu_count() + 4) cpu逻辑核心数加4和32中的较小值(3.8)
- _4核8线程_,8就是逻辑核心数
- initializer是一个可调用对象,如果不为空会在每个工作线程开始运行时调用。initargs是其元组参数
from concurrent.futures import ThreadPoolExecutor , as_completed
import time 
import threading

def init(args):
    """initializer只会在工作线程刚开始运行的时候掉调用, 工作线程切换任务后不会再次调用"""
    print(f"{threading.current_thread().name} initializer {args} : {time.strftime('%X')}")

def f(name,i):
    print(f"{threading.current_thread().name}-{name}: start at {time.strftime('%X')}: sleep{i}s")
    time.sleep(i)
    return f"{threading.current_thread().name}-{name} done at {time.strftime('%X')}"


if __name__ =="__main__":
    with ThreadPoolExecutor(max_workers=5, thread_name_prefix='w_thread',initializer=init, initargs=('initargs',)) as pool:
        
        fs = [pool.submit(f, i+1,i+1) for i in range(10)]
        for future in as_completed(fs):
            print(future.result())
        

concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=())

- max_workers的默认值为cpu核个数最大为61,windows上最大值为61
from concurrent.futures import ProcessPoolExecutor, as_completed
import math 
import time 


PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419,
    1099726899285417,
    1099726899285410,
    ]
def is_prime(n):
    
    if n<2:
        return False 
    if n==2:
        return True 
    if n%2==0:
        return False
    for i in range(3,int(math.sqrt(n))+1, 2):
        if n%i==0:
            return False 
    return True 

if __name__ =="__main__":
    with ProcessPoolExecutor() as pool:
        fs = [pool.submit(is_prime, prime) for prime in PRIMES]
        for future in as_completed(fs):
            print(future.result())
        # print(pool._max_workers )

concurrent.futures.Future

Future实例由Executor.submit()创建,将可调用对象封装为异步执行,Future实例由Executor.submit()创建,除非测试,不应直接创建.

  1. cancel():
    • 尝试取消调用,如果正在执行或已结束不能被取消返回False,否则任务会被取消,并且该方法将返回True
  2. cancelled(): 成功取消返回True
  3. running():正在运行返回True
  4. done(): 如果被取消或正常结束返回True
  5. result(timeout=None): 获取任务的返回值,如果timeout不为None,超时会引发concurrent.futures.TimeoutError,如果future在完成钱被取消则引发CancelledError
  6. add_done_callback(fn): 添加回调函数,fn直接说一个参数即这个future对象
  7. execption(timeout=None): 返回由调用引发的异常,可以等待timeout秒。

模块函数

  1. concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)
    • 等待fs中的Future对象完成,返回一个二元组,第一个集合为正常结束或被取消的future,第二个集合为未完成的future
    • return_when: 1. FIRST_COMPLETED任意对象结束或被取消时返回 2. FIRST_EXCEPTION 任意对象发生异常时返回,如果没有异常相当于ALL_COMPLETED 3. ALL_COMPLETED所有可等待对象结束或返回
  2. concurrent.futures.as_completed(fs, timeout=NOne)
    • 返回一个包含fs所指定的Future对象的迭代器。按照任务返回的先后顺序,先运行完的任务在最前。
posted @ 2022-07-06 22:01  店里最会撒谎白玉汤  阅读(530)  评论(0)    收藏  举报