Python中async/await与Golang协程的易用性对比

最近在看 async/await 模型的协程,貌似 async 必须 await..

Golang 首先不用 await 一个 courotine,其次可以 select+channel...

你们可以教教我怎么 async+await 实现并发协程么?


Python中async/await与Golang协程的易用性对比
26 回复

两者其实不是一个层级的东西,asyncio 只是暴露了协程的 Python 接口供开发者使用,充其量就是加了点语法糖。Golang 则是建立在 CSP model 上来调度协程,底层已经封装了很多东西了。

更多关于Python中async/await与Golang协程的易用性对比的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Python的async/await和Golang的goroutine在并发模型上走了两条不同的路。

Python的async/await是协作式多任务,你需要显式地用async定义协程,用await交出控制权。它基于事件循环,适合I/O密集型场景。写起来得时刻注意哪些函数是异步的,用错了await或者混用了同步代码就容易出问题。

Golang的goroutine是抢占式多任务,用个go关键字就能启动,调度器在背后管。它更接近传统多线程的感觉,但通信得靠channel,避免了共享内存的坑。语法上更干净,心智负担小。

简单说,Python的async/await控制精细但得小心翼翼,Golang的goroutine写起来顺手但得适应channel通信。选哪个看项目需求和个人偏好。

我理解目前 asyncio 能做的就是把常用的 tcp server 重度封装一下,把 accept 阶段扇出 coroutine 的事情帮用户做了,剩下的基本靠用户自己基于 event driven loop+generator 再封装的样子。

#2 asyncio 是操作系统层面的协程接口,csp 是并发模型

event driven 本身是并发的,结果语法糖到 await,async 上变成了串行的,附赠了一个 wait_all 之类的糖说可以并发,感觉略扯。

你把 golang 的协程当成别一种线程就容易理解了

很多年前造过 C+lua 协程的网络框架,实际上也是在 C 层把常用的 server 和 read/write api 都封装好了,直接给 connection 协程用,所以当时并没有觉得这种协程模型难受。

链接: http://bbs.chinaunix.net/thread-4076795-1-1.html

但是我觉得在一个提倡简单的脚本语言里搞这种半成品,实在是费解。

暂时没好的解决方案,将个烂就

照我看,asyncio 里的 loop 可能比较有用,其他的语法就算了 -,-#

竟然有 goless 这种库,配合 gevent 模拟 go 的 csp 模型

继续 gevent 走起。

说到 goless 我就想起了 offset ( https://github.com/benoitc/offset ),这个还重写了异步版标准库,可惜基于 fiber,有些弱。不过这俩库的作者貌似都弃坑了…… 之前我都玩过一下,好像效果跟 golang 的还是有些差异

async/await 是 C#最先用的吧,然后是 Python,JS,
不过 python 里面搞的确实复杂了,flask 作者就写过一篇文章:
http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/

go func 就我这种菜鸟都会用了。

老玩家,难道你已经看透

了解一下

gevent +1

一直有个问题想不明白,Lua 的 coroutine 是协作调度的,也就是说当前执行的 coroutine 自己主动 yield 出去,其他 coroutine 才有机会执行。那如果当 coroutine 遇到了会 block 的操作时,怎么 yield 出去,什么时候 yield ?不然不在被 block 时 yield 出去,怎么做到多个 coroutine 并发的效果呢?

lua 实际上是为 c 服务的,主体在 c。lua 有协程能力,简单说就是保存上下文暂停执行( yield ),让你感觉同步写逻辑。c 有事件驱动能力,为 lua api 提供异步能力。所以 c 基本是做服务框架和 lua api 的异步逻辑,而 lua 做 api 的壳以及切换到 c 异步事件之前的 yield 调用。

补充一下,c 在事件完成后 resume lua 的协程。

gevent 我还需要再看看特性,有类线程和队列,但没有多路。

说到底 py3 的 async/await 本质上只是生成器和迭代器的语法糖,而 golang 的 go func 是语言级别的并发模型,两者自然没有可比性
python 标准库中大部分的 api 都是阻塞式的,不可能为了支持协程而大范围修改系统库(为了兼容性),虽然 gevent 的 monkey patch 可以实现把整个系统的线程都改成协程操作的,不过如果调用了 c 库就会阻塞整个程序(需要自己对 gevent.ThreadPool 进行封装调用)
而 golang 的 runtime 在底层就是实现了 n 对 m 的线程+协程模型,当然比 py3 的语法糖强多了

gevent 是有多路的,通过 libev 实现了对 socket api 的多路复用

我是指 select 多路 channel

python 这个 asyncio 第一天粗看了一遍文档看得云里雾里,还好晚上想了一.晚想通了,不如像 js 这样简单化处理

有像 join 的 asyncio.gather,还有一个类似 select 的 asyncio.wait,要是没啥依赖,直接丢 asyncio.create_task

回到顶部