Python 官方文档:入门教程 => 点击学习
目录1、前言2、什么是协程?3、混乱的历史3.1python协程的进化4、javascript协程的进化5、Python协程成熟体5.1协程(coroutine)5.2任务(Task
总结一句话,协程就是满足下面条件的函数:
- 可以暂停执行(暂停的表达式称为暂停点)
- 可以从挂起点恢复(保留其原始参数和局部变量)
- 事件循环是异步编程的底层基石
yield from
(yield from
约等于 yield
+ 异常处理 + send
), 并试验性引入的异步 I/O 框架 asyncio
(PEP 3156)async/await
语法(PEP 492)asyncio
库"转正" (之后的官方文档就清晰了很多)在主线发展过程中,也出现了很多支线的协程实现如 Gevent
。
def foo():
print("foo start")
a = yield 1
print("foo a", a)
yield 2
yield 3
print("foo end")
gen = foo()
# print(gen.next())
# gen.send("a")
# print(gen.next())
# print(foo().next())
# print(foo().next())
# 在python3.x版本中,python2.x的g.next()函数已经更名为g.__next__(),使用next(g)也能达到相同效果。
# next()跟send()不同的地方是,next()只能以None作为参数传递,而send()可以传递yield的值.
print(next(gen))
print(gen.send("a"))
print(next(gen))
print(next(foo()))
print(next(foo()))
list(foo())
"""
foo start
1
foo a a
2
3
foo start
1
foo start
1
foo start
foo a None
foo end
"""
callback hell
Promise/a+,
生成器 Generators
(语法 function foo(){}*
可以赋予函数执行暂停/保存上下文/恢复执行状态的功能), 新关键词 yield 使生成器函数暂停。Generator
函数和自动执行器,包装在一个函数里),此函数需要返回一个 Promise
对象。await
可以等待一个 Promise
对象 resolve
,并拿到结果Promise
中也利用了回调函数。在 then
和 catch
方法中都传入了一个回调函数,分别在 Promise
被满足和被拒绝时执行,这样就就能让它能够被链接起来完成一系列任务。
总之就是把层层嵌套的 callback
变成 .then().then()...,
从而使代码编写和阅读更直观。
生成器 Generator
的底层实现机制是协程 Coroutine
。
function* foo() {
console.log("foo start")
a = yield 1;
console.log("foo a", a)
yield 2;
yield 3;
console.log("foo end")
}
const gen = foo();
console.log(gen.next().value); // 1
// gen.send("a") // Http://www.voidcn.com/article/p-syzbwqht-bvv.html SpiderMonkey引擎支持 send 语法
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(foo().next().value); // 1
console.log(foo().next().value); // 1
可等待对象可以在 await
语句中使用,可等待对象有三种主要类型:协程(coroutine
), 任务(task
) 和 Future
。
async def
的函数;generator
(生成器)的协程 asyncio.create_task()
等函数被封装为一个 任务,该协程会被自动调度执行Future
对象,Task 对象会挂起该协程的执行并等待该 Future 对象完成。当该 Future
对象 完成,被打包的协程将恢复执行。asyncio.Task
从 Future
继承了其除 Future.set_result()
和 Future.set_exception()
以外的所有 api。 Future
对象用来链接 底层回调式代码 和高层异步/等待式代码。
不用回调方法编写异步代码后,为了获取异步调用的结果,引入一个 Future
未来对象。Future
封装了与 loop
的交互行为,add_done_callback
方法向 epoll 注册回调函数,当 result
属性得到返回值后,会运行之前注册的回调函数,向上传递给 coroutine
。
libevent/libev:
Gevent(greenlet + 前期 libevent,后期 libev)使用的网络库,广泛应用; tornado:
tornado 框架自己实现的 IOLOOP; picoev:
meinheld(greenlet+picoev
)使用的网络库,小巧轻量,相较于 libevent 在数据结构和事件检测模型上做了改进,所以速度更快。但从 GitHub 看起来已经年久失修,用的人不多。 uvloop:
Python3 时代的新起之秀。Guido 操刀打造了 asyncio 库,asyncio
可以配置可插拔的event loop
,但需要满足相关的 API 要求,uvloop 继承自 libuv,将一些低层的结构体和函数用 Python 对象包装。目前 Sanic 框架基于这个库例子:
import asyncio
import time
async def exec():
await asyncio.sleep(2)
print('exec')
# 这种会和同步效果一直
# async def Go():
# print(time.time())
# c1 = exec()
# c2 = exec()
# print(c1, c2)
# await c1
# await c2
# print(time.time())
# 正确用法
async def go():
print(time.time())
await asyncio.gather(exec(),exec()) # 加入协程组统一调度
print(time.time())
if __name__ == "__main__":
asyncio.run(go())
Promise
本质是一个状态机,用于表示一个异步操作的最终完成 (或失败), 及其结果值。它有三个状态:
pending:
初始状态,既不是成功,也不是失败状态。 fulfilled:
意味着操作成功完成。rejected
: 意味着操作失败。最终 Promise
会有两种状态,一种成功,一种失败,当 pending
变化的时候,Promise 对象会根据最终的状态调用不同的处理函数。
async
、await
是对 Generator
和 Promise
组合的封装,使原先的异步代码在形式上更接近同步代码的写法,并且对错误处理/条件分支/异常堆栈/调试等操作更友好。
task queue
)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。遇到同步任务直接执行,遇到异步任务分类为宏任务(Macro-task
)和微任务(micro-task
)。
当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
例子:
var sleep = function (time) {
console.log("sleep start")
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
});
};
async function exec() {
await sleep(2000);
console.log("sleep end")
}
async function go() {
console.log(Date.now())
c1 = exec()
console.log("-------1")
c2 = exec()
console.log(c1, c2)
await c1;
console.log("-------2")
await c2;
console.log(c1, c2)
console.log(Date.now())
}
go();
主线程循环从"任务队列"中读取事件
宏队列(macro task
)js 同步执行的代码块,setTimeout
、setInterval
、XMLHttprequest
、setImmediate
、I/O、UI rendering
等,本质是参与了事件循环的任务
微队列(micro task)Promise
、process.nextTick
(node环境)、Object.observe
, MutationObserve
r等,本质是直接在 Javascript 引擎中的执行的没有参与事件循环的任务
扩展阅读 node.js 中的 EventLoop (Javascript 运营机制详解再浅谈 Event Loop)
说明 | python | JavaScript | 点评 |
---|---|---|---|
进程 | 单进程 | 单进程 | 一致 |
中断/恢复 | yield,yield from,next,send | yield,next | 基本相同,但 JavaScript 对 send 没啥需求 |
未来对象(回调包装) | Futures | Promise | 解决 callback,思路相同 |
生成器 | generator | Generator | 将 yield 封装为协程Coroutine,思路一样 |
成熟后关键词 | async、await | async、await | 关键词支持,一毛一样 |
事件循环 | asyncio 应用的核心。事件循环会运行异步任务和回调,执行网络 IO 操作,以及运行子进程。asyncio 库支持的 API 较多,可控性高 | 基于浏览器环境基本是黑盒,外部基本无法控制,对任务有做优先级分类,调度方式有区别 | 这里有很大区别,运行环境不同,对任务的调度先后不同,Python 可能和 Node.js 关于事件循环的可比性更高些,这里还需需要继续学习 |
到此这篇关于Python 协程与 JavaScript 协程的对比的文章就介绍到这了,更多相关Python 协程与 JavaScript 协程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Python 协程与 JavaScript 协程的对比
本文链接: https://www.lsjlt.com/news/135899.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0