python2协程_Python笔记(二十二)协程asyncio-2:常用API-Go语言中文社区

loop

asyncio.get_event_loop():获得当前context的loop

asyncio.new_event_loop():创建一个新的loop对象

asyncio.set_event_loop(loop):为当前context设置loop

关于context,推测为当前线程的上下文环境。如果asyncio的loop和android中的handler相似,那每条线程都可以有一个loop。不过一般也都只用get_event_loop()就行了

loop的常用API

run_until_complete(future):运行future,并阻塞当前线程直到future运行完毕

run_forever():运行future,并阻塞当前线程,直到该loop的stop()方法被调用

由于run_forever()会一直阻塞当前线程,故只能在future中调用loop的stop()方法

run_forever()stop前未完成的future将在下次执行run_forever()后继续执行。具体的策略我还没搞清楚

stop():停止loop

is_running()

close():关闭loop,所有Pending状态的future和callback函数都将被丢失,且之后不能再运行这个loop

is_close()

call_soon(callback,*args):安排一个函数被尽快执行

call_soon_threadsafe(callback, *args):同上,但是线程安全

call_later(delay, callback, *args):delay的单位是秒

call_at(when, callback, *args):when是一个时间戳

call_soon依旧需要调用loop的run_until_complete或者run_forever才会去执行callback函数,callback就是一个普通函数

call_soon不能把关键字参数传递给callback,如果希望这么做,可以结合functools.partial

loop.call_soon(functools.partial(print, "Hello", flush=True))

大多数asyncio的对象都不是线程安全的,如果需要访问event loop中的对象,就需要使用call_soon_threadsafe方法。比如希望取消一个future,不能直接使用future.cancel,而需要loop.call_soon_threadsafe(future.cancel)

loop的call相关的方法都会返回一个Handle对象,该对象的cancel方法可以用来取消callback函数的执行。如果callback已经被执行或取消,则cancel不起作用

run_coroutine_threadsafe(coro_func,loop):loop必须在主线程中运行,如果希望其他线程去执行协程,需要调用该方法,该方法返回一个Future对象

run_in_executor(executor, func, *args):用ThreadPoolExecutor来执行函数,executor为None,则使用默认的executor

set_default_executor(executor)

如果希望在coroutine中执行异步IO,可以使用run_in_executor方法

Future和Task

几乎兼容concurrent.futures.Future,它包含的方法也几乎等同于concurrent.futures.Future

future有四种状态:Pending、Running、Done、Cancelled

coroutine是协程

future是协程运行的结果

Task是Future的子类,是loop真正执行的任务

应该可以这么理解coroutine被包装成一个task给loop调度执行,而coroutine的await/yield from返回一个future作为其异步操作的执行结果

future可以用add_done_callback设置回调函数,该回调函数会被传入一个参数,参数的值就是当前的future对象

asyncio模块的其他函数

ensure_future(coro_or_future, *, loop=None):安排coroutine对象的执行,返回一个task,该task将在下次loop.run_until_complete或loop.run_forever后被执行;如果loop已经在执行了,那该coroutine会被安排到本次loop的执行中,而不是下一次;如果参数不是coroutine,而是future,则直接返回

gather(*coros_or_futures, loop=None, return_exceptions=False):聚合多个coroutine或者future,返回一个future,直到所有任务都完成后,该future才返回

wait(futures, *, loop=None, timeout=None, return_when=ALL_COMPLETED):类似于gather,聚合future,当然它有其他两种返回时机(FIRST_COMPLETED/FIRST_EXCEPTION)

wait和gather的第一个参数是有很大不同的!

wait接收的是一个future的序列,而gather接收的是任意数量的coroutine或gather对象,也就是说如果有一个coro_seq希望传递给gather,则需要使用*coro_seq

wait返回的是一个generator;而gather返回的是一个future,可以设置callback函数哦

as_completed(fs, *, loop=None, timeout=None):和concurrent.future.as_completed有很大不同。

对于concurrent.future,是执行完一个future,就返回该future,然后即可通过future的result方法来回去结果

对于asyncio,as_completed返回的是一个元素为coroutine的iterator,因为它接收的参数也可以是一个元素为coroutine/future的iterator,感觉像是它对传入的coroutine做了包装?

使用result = await coroutine可以获得原coroutine的返回结果

async def coro_func():

for f in as_completed(fs):

result = await f

从现象上来看,上述代码的for循环中第一次await的时候就会执行完fs中所有的future,后续的await就是直接从future中拿结果,几乎不耗时

可以理解为:as_completed并发执行完所有fs中的coroutine,同时也保持了coroutine的执行顺序

虽然所有coroutine也是并发执行的,但是当前线程却要等到所有coroutine都执行完毕后才能继续,感觉没concurrent.future的as_completed快

多说一句,很容易想当如果直接用for循环迭代fs,而不加as_completed函数的话,就不能达到多个coroutine并发的效果了

asyncio模块提供API来创建子进程以执行shell命令,就像subprocess模块!

asyncio模块提供同步相关的API,lock、event、condition、semaphore等

asyncio也提供普通队列,LIFO队列,优先级队列等API

协程提供了一些与线程的API相对应的API,我觉得协程可以理解为一种线程,这种线程可以指定何时让出CPU

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值