concurrent.futures 模块提供一个高级别接口给调用异步执行
异步执行可以用线程执行,使用
ThreadPoolExecutor,或者单独的进程使用
ProcessPoolExecutor,两者都实行了相同的接口,它由
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:
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。
使用最多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将立即被调用
下面的方法将用于单元测试和执行器实现。