线程池 concurrent.futures

concurrent.futures 模块提供一个高级别接口给调用异步执行
异步执行可以用线程执行,使用 ThreadPoolExecutor,或者单独的进程使用 ProcessPoolExecutor,两者都实行了相同的接口,它由
抽象  Executor类定义 #也就是说 ThreadPoolExecutorProcessPoolExecutor都继承了  Executor类可调用里面的方法。
 

Executor Objects

class concurrent.futures.Executor
    这个抽象类提供方法去执行调用异步。它不能直接使用,而是通过它具体的子类
submit(fn, *args, **kwargs)
    它是异步提交任务,将可调用的fn作为fn(*args,**kwargs)执行,并返回表示可调用的执行的future函数
   
withThreadPoolExecutor(max_workers=1) as executor:
   future =executor.submit(pow, 323, 1235)
   print(future.result())
 
map(func, *iterables, timeout=None, chunksize=1)
    类似  map(func, *iterables)除了以下:
       迭代器是立即收集的而不是延迟收集的
       func是异步执行的和对func的多个调用可以并发执行
    timeout:
    如果 __next__()的结果不可用在超时几秒后会返回迭代器引发的  concurrent.futures.TimeoutError,超时时间在 Executor.map()中定义
    timeout可以是一个整数或者小数,如果timeout没有指定或者None,等待时间没有限制。
    如果调用引发了一个异常,当迭代器检索它的值时异常将被引发。
    chunksize:
   当使用 ProcessPoolExecutor,这个方法将迭代器分割成许多块,并将这些块作为单独的任务提交给池,可以用正整数指定chunksize的大小。
    对于非常长的迭代,与默认大小1相比,使用大的chunksize值可以显著的提高性能。
    如果使用 ThreadPoolExecutor,chunksize将没有效果。
 
shutdown(wait=True)    向执行程序发出释放任何资源的信号,在关闭后调用Executor.submit()和Executor.map()将引发运行时错误。如果wait为真,那么该方法将不会返回,直到所有未执行的期货都已执行,并且与执行器关联的资源被释放。如果wait时flase,该方法将立刻返回,当所有未执行的期货执行完毕时,与执行器关联的    资源将被释放。不管等待的值是多少,整个python程序将不会退出,直到执行完所有未完成的futures。       如果使用with语句,则可以避免调用此方法(等待,就像调用  Executor.shutdown()将wait设置为True)

ThreadPoolExecutor

ThreadPoolExecutor是executor的子类,使用线程池异步执行调用。
当与future关联的可调用对象等待另一个future的结果时,可能会发生死锁。例如:
importtime
defwait_on_b():time.sleep(5)
print(b.result()) # b will never complete because it is waiting on a.
return5
 
defwait_on_a():time.sleep(5)
print(a.result()) # a will never complete because it is waiting on b.
return6
executor =ThreadPoolExecutor(max_workers=2)
a =executor.submit(wait_on_b)
b =executor.submit(wait_on_a)
And:
defwait_on_future():
   f =executor.submit(pow, 5, 2)
   # This will never complete because there is only one worker thread and
   # it is executing this function.
   print(f.result())
executor =ThreadPoolExecutor(max_workers=1)
executor.submit(wait_on_future)
 
class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())
   max_workers:
   一个Executor子类,它使用最多max_workers线程池异步执行调用。如果 max_workers是none或者没给,线程数将是机器处理器的数量乘以5,
   initializer(初始化器),initargs:
   initializer是可选可调用项,调用在每个工作线程的开始,initargs是传递给initializer的一组参数,如果初始化器引发异常,所有当前挂起的工作将引发
    一个 BrokenThreadPool,以及任何尝试提交更多任务给地址池。假设ThreadPoolExecutor经常用于重复I/O而不是CPU工作,workers的数量应该
    高于 ProcessPoolExecutorworker数量.
   thread_name_prefix:
    更新在3.6版本,thread_name_prefix参数将增加同意控制threding的用户,为便于调试,池创建的工作线程的线程名。
    更新在3.7版本:增加initializerand initargs 参数

ThreadPoolExecutor Example

importconcurrent.futures
importurllib.requestURLS =[' http://www.foxnews.com/',
 
# Retrieve a single page and report the URL and contents
defload_url(url,timeout):
withurllib.request.urlopen(url,timeout=timeout) asconn:
returnconn.read()
 
# We can use a with statement to ensure threads are cleaned up promptly
withconcurrent.futures.ThreadPoolExecutor(max_workers=5) asexecutor:
# Start the load operations and mark each future with its URLfuture_to_url ={executor.submit(load_url,url, 60):url forurl inURLS}
forfuture inconcurrent.futures.as_completed(future_to_url):url =future_to_url[future]
try:data =future.result()
exceptExceptionasexc:
print('%rgenerated an exception: %s'%(url,exc))
else:
print('%rpage is %dbytes'%(url, len(data)))
 

ProcessPoolExecutor

ProcessPoolExecutor类是Executor子类使用进程池异步执行调用。 ProcessPoolExecutor使用 multiprocessing模块,允许他避开 Global Interpreter Lock,但同时意味着只有picklable对象能执行和返回
__main__模块必须能被工作子进程倒入,这意味着 ProcessPoolExecutor将不工作在交互解释器。
从提交给ProcessPoolExecutor的可调用对象调用Executor或future的方法将导致死锁。
 
class concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=())

使用最多max_workers进程池异步执行调用的Executor子类,如果max_workers是None或不给,他将默认为机器上的处理器数量,如果max_workers小于或等于0,将会引发ValueError。mp_context可以是多处理上下文,也可以是无处理上下文,他将用于发射worker。如果mp_context是none或者没给,默认multiprocessing context 被使用
初始化项是可选的可调用项,在每个工作进程开始时调用;initargs是一个元祖参数传递给 initializer,如果initializer引发一个异常,所有当前挂起的任务将引发一个  BrokenProcessPool,以及任何向池提交更多作业的尝试。
更改在version3.3:当一工作进程突然中止,就会引发一个BrokenProcessPool 错误,以前,行为是未定义的,但是对执行者或其未来的操作通常会冻结或死锁更改在version3.7:添加mp_context参数是为了允许用户控制由池创建的工作进程的start_method。

ProcessPoolExecutor Example

importconcurrent.futures
importmathPRIMES =[
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
 
defis_prime(n):
ifn %2==0:
returnFalsesqrt_n =int(math.floor(math.sqrt(n)))
fori inrange(3,sqrt_n +1, 2):
ifn %i ==0:
returnFalse
returnTrue
 
defmain():
withconcurrent.futures.ProcessPoolExecutor() asexecutor:
fornumber,prime inzip(PRIMES,executor.map(is_prime,PRIMES)):
print('%dis prime: %s'%(number,prime))
 
if__name__=='__main__':main()
 

Future Objects

future类封装了可调用的异步执行。future实例是由 Executor.submit()创建的
class concurrent.futures.Future封装了可调用的异步执行。future是由 Executor.submit()创建的,除测试意外,不能够直接创建cancel() 尝试去取消调用。如果是当前执行调用,且无法取消的,则该方法则返回False,否则调用将取消并且该方法将返回Truecancelled()如果调用是成功取消的,返回True,running() 如果调用是当前正在执行的并且没有取消,返回True,done()如果调用成功取消或完成运行返回Trueresult(timeout=None)返回调用返回的值,如果这个调用还没有完成这个方法将等待timeout seconds,如果调用还没完成在timeout seconds内,将引发一个 concurrent.futures.TimeoutError,timeout能是整数或浮点数,如果超时没有指定或None,等待时间将没有限制
如果在完成之前future取消将引发 CancelledError
如果引发调用,此方法将引发相同的异常。
exception(timeout=None)返回调用引发的异常。返回调用返回的值,如果这个调用还没有完成这个方法将等待timeout seconds,如果调用还没完成在timeout seconds内,将引发一个 concurrent.futures.TimeoutError,timeout能是整数或浮点数,如果超时没有指定或None,等待时间将没有限制
如果在完成之前future取消将引发 CancelledError
如果引发调用,此方法将引发相同的异常。add_done_callback(fn)将可调用的fn附加到future。当future被取消或完成运行时,将调用fn,并将future作为其唯一参数。添加的callables按添加顺序调用,并且始终在属于添加它们的进程的线程中调用。如果被调用引发一个 Exception子类,他将被记录或者忽视。如果调用方引发一个 BaseException子类,行为是没有定义的。如果future已经完成或者已经取消,fn将立即被调用
下面的方法将用于单元测试和执行器实现。

猜你喜欢

转载自www.cnblogs.com/BALCKLIGHTNING/p/10067590.html