对于协程, 一些使用装饰器或者队列的实例基本都能理解, 但是这个 async/await 看了很多实例也不太懂该怎么理解. 网上 90%的教程的例子大概基本都是这样的:
async def func():
print("start...")
r = await asyncio.sleep(5)
print("end...")
这个 asyncio.sleep()从一开始就定义是非阻塞的, 问题是它到底是通过什么方式实现非阻塞的呢? 换成我自己的处理函数, 这个函数应该用什么方式协程非阻塞的?
1
shylockhg 2019-01-25 11:49:55 +08:00
asyncio.sleep 就是阻塞的,这里是模拟 IO 等阻塞过程
|
3
aoscici2000 OP @shylockhg 我疑问就是这里了, 这个非阻塞是通过什么方式实现的?
|
4
so1n 2019-01-25 12:07:09 +08:00 via Android
@aoscici2000 通过事件循环,3.4 时是 yield
|
5
aoscici2000 OP @so1n 意思是该开线程还得开, 该 yield 还得 yield, 就是换了个词而已 ???
|
6
silkriver 2019-01-25 12:23:33 +08:00 via Android
不开线程,异步 io 的意思就是 io 操作不会阻塞当前线程
|
7
meik2333 2019-01-25 12:31:41 +08:00 via Android
https://github.com/python/cpython/blob/97cf0828727ac2a269c89c5aa09570a69a22c83c/Lib/asyncio/tasks.py#L593
将事件添加到事件循环里,由事件循环调度。 scrapy 也是用这种方法实现每分钟打印一次日志的。 |
8
Trim21 2019-01-25 12:34:12 +08:00
你可以看看源码, asyncio.sleep 是通过在事件循环里 call_later 来实现的. 在这个 async 函数中阻塞, 但是不会阻塞事件循环.
作用就是模拟异步 io 操作. 所以换成你自己的处理函数的时候, 比如是链接数据库, http 请求这样的可以异步化的, 就用类似的异步化的库(比如 aiohttp, aioredis, motor 等等)来 await query()调用. 如果不能异步化的就开线程用 ThreadPoolExecutor 转成异步调用. |
9
aijam 2019-01-25 12:39:05 +08:00
解释线程 /异步 /非阻塞 /event loop 的文章网上一大堆,你看了也不会真的懂。
先熟悉熟悉这个包: https://docs.python.org/3/library/selectors.html#module-selectors https://docs.python.org/3/library/select.html#module-select 他们说的再多虚头巴脑都扯淡,核心内容就是 selector。 |
10
xinXinDaWang 2019-01-30 16:17:30 +08:00
那你要看很多了,future, loop, epoll 都要看, 是他们相互协作形成的,await==yield from 只是一个方便的写法,也可以用回调来写,只是会麻烦一些
|