iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python 协程与 JavaScript 协程的对比
  • 163
分享到

Python 协程与 JavaScript 协程的对比

2024-04-02 19:04:59 163人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录1、前言2、什么是协程?3、混乱的历史3.1python协程的进化4、javascript协程的进化5、Python协程成熟体5.1协程(coroutine)5.2任务(Task

1、前言

  • 随着 cpu 多核化,都需要实现由于自身历史原因(单线程环境)下的并发功能
  • 简化代码,避免回调地狱,关键字支持
  • 有效利用操作系统资源和硬件:协程相比线程,占用资源更少,上下文更快

2、什么是协程?

总结一句话,协程就是满足下面条件的函数:

  •  可以暂停执行(暂停的表达式称为暂停点)
  •  可以从挂起点恢复(保留其原始参数和局部变量)
  •  事件循环是异步编程的底层基石

3、混乱的历史

3.1 Python 协程的进化

  • Python2.2 中,第一次引入了生成器
  • Python2.5 中,yield 关键字被加入到语法中
  • python3.4 时有了 yield fromyield from 约等于 yield + 异常处理 + send), 并试验性引入的异步 I/O 框架 asyncio(PEP 3156)
  • Python3.5 中新增了 async/await 语法(PEP 492)
  • Python3.6 中 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  
""" 

4、JavaScript 协程的进化

  • 同步代码
  • 异步 JavaScript: callback hell
  • es6 引入 Promise/a+, 生成器 Generators(语法 function foo(){}* 可以赋予函数执行暂停/保存上下文/恢复执行状态的功能), 新关键词 yield 使生成器函数暂停。
  • ES7 引入 async函数/await语法糖,async 可以声明一个异步函数(将 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  
 

5、Python 协程成熟体

可等待对象可以在 await 语句中使用,可等待对象有三种主要类型:协程(coroutine), 任务(task) 和 Future

5.1 协程(coroutine)

  • 协程函数:定义形式为 async def 的函数;
  • 协程对象:调用 协程函数 所返回的对象
  • 旧式基于 generator(生成器)的协程

5.2 任务(Task 对象)

  • 任务 被用来“并行的”调度协程, 当一个协程通过 asyncio.create_task() 等函数被封装为一个 任务,该协程会被自动调度执行
  • Task 对象被用来在事件循环中运行协程。如果一个协程在等待一个 Future 对象,Task 对象会挂起该协程的执行并等待该 Future 对象完成。当该 Future 对象 完成,被打包的协程将恢复执行。
  • 事件循环使用协同日程调度: 一个事件循环每次运行一个 Task 对象。而一个 Task 对象会等待一个 Future 对象完成,该事件循环会运行其他 Task、回调或执行 IO 操作。
  • asyncio.Task Future 继承了其除 Future.set_result() Future.set_exception() 以外的所有 api

5.3 未来对象(Future)

 Future 对象用来链接 底层回调式代码 和高层异步/等待式代码。
 不用回调方法编写异步代码后,为了获取异步调用的结果,引入一个 Future 未来对象。Future 封装了与 loop 的交互行为,add_done_callback 方法向 epoll 注册回调函数,当 result 属性得到返回值后,会运行之前注册的回调函数,向上传递给 coroutine

5.4几种事件循环(event loop)

  • 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()) 

6、JavaScript 协程成熟体

6.1Promise 继续使用

Promise 本质是一个状态机,用于表示一个异步操作的最终完成 (或失败), 及其结果值。它有三个状态:

  •  pending: 初始状态,既不是成功,也不是失败状态。
  •  fulfilled: 意味着操作成功完成。
  •  rejected: 意味着操作失败。

最终 Promise 会有两种状态,一种成功,一种失败,当 pending 变化的时候,Promise 对象会根据最终的状态调用不同的处理函数。

6.2 async、await语法糖

asyncawait 是对 Generator Promise 组合的封装,使原先的异步代码在形式上更接近同步代码的写法,并且对错误处理/条件分支/异常堆栈/调试等操作更友好。

6.3 js 异步执行的运行机制

  • 所有任务都在主线程上执行,形成一个执行栈。
  •  主线程之外,还存在一个"任务队列"(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();

6.4 event loop 将任务划分

 主线程循环从"任务队列"中读取事件
 宏队列macro task)js 同步执行的代码块,setTimeoutsetIntervalXMLHttprequestsetImmediate、I/O、UI rendering等,本质是参与了事件循环的任务
微队列(micro task)Promiseprocess.nextTicknode环境)、Object.observeMutationObserver等,本质是直接在 Javascript 引擎中的执行的没有参与事件循环的任务
扩展阅读 node.js 中的 EventLoop (Javascript 运营机制详解再浅谈 Event Loop)

7、总结与对比

说明 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文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python 协程与 JavaScript 协程的对比
    目录1、前言2、什么是协程?3、混乱的历史3.1Python协程的进化4、JavaScript协程的进化5、Python协程成熟体5.1协程(coroutine)5.2任务(Task...
    99+
    2024-04-02
  • Golang 与 JavaScript 的协程对比
    问题:go 和 javascript 中的协程有何差异?回答:栈: go 协程有自己的栈,javascript 保存协程的状态在 promise 对象中。调度: go 协程由 gorou...
    99+
    2024-05-12
    协程 对比 golang
  • PHP 多线程与 Go 协程对比?
    php 多线程和 go 协程都是高并发场景下的有效机制。多线程提供了强大的管理功能,但开销较大,而协程非常轻量,开销更小。在实战中,php 多线程适合并发爬虫等任务,而 go 协程更适合...
    99+
    2024-05-12
    go php
  • python协程与golang协程的区
    进程、线程和协程 进程的定义: 进程,是计算机中已运行程序的实体。程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。 线程的定义: 操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。 进程...
    99+
    2023-01-31
    python golang
  • Golang中线程与协程的对比分析
    Golang中线程与协程的对比分析 在现代的软件开发中,多线程编程是一项非常常见的任务。而随着硬件技术的发展,多核处理器已经成为了主流,因此利用多线程并行处理数据已经成为了提高程序性能...
    99+
    2024-02-29
    golang 线程 协程 go语言
  • WebSocket协议与TCP协议的对比与选择
    在网络通信中,TCP协议是一种可靠的传输协议,广泛应用于各种网络通信场景。而WebSocket协议则是一种基于HTTP的应用层协议,它提供了双向通信的能力,使得客户端和服务器之间可以实时地进行数据交互。本文将对WebSocket协议和TCP...
    99+
    2023-10-21
    它提供可靠的数据传输 错误检测和拥塞控制。
  • java协程框架quasar和kotlin中的协程对比分析
    目录前言快速体验添加依赖添加java agent线程VS协程协程代码多线程代码协程完胜后记前言 早就听说Go语言开发的服务不用任何架构优化,就可以轻松实现百万级别的qps。这得益于G...
    99+
    2024-04-02
  • 对比Golang协程和线程的异同
    Golang协程和线程的异同对比 在软件开发中,线程和协程是实现并发编程的两种常见方式。而在Golang语言中,协程(Goroutine)是一种轻量级的并发编程模型,与传统的线程(Thread)相比,具有一些...
    99+
    2024-01-24
    - 线程 - 异同对比
  • 对比Golang协程和线程的分析
    Golang协程与线程的差异解析 在现代编程语言中,多线程并发已经成为一种常见的编程模式,用于提高程序的性能和响应能力。然而,线程的创建和管理往往需要消耗大量的系统资源,同时在编程复杂性和错误处理上也存在一些...
    99+
    2024-01-24
  • python3--进程,线程,协程效率对比
    需求:写一个脚本,判断192.168.11.0/24网络里,当前在线ip有哪些?知识点:1 使用subprocess模块,来调用系统命令,执行ping 192.168.11.xxx 命令2 调用系统命令执行ping命令的时候,会有返回值(p...
    99+
    2023-01-30
    线程 进程 效率
  • Python:线程、进程与协程(7)——
         前面转载了一篇分析进程池源码的博文,是一篇分析进程池很全面的文章,点击此处可以阅读。在Python中还有一个线程池的概念,它也有并发处理能力,在一定程度上能提高系统运行效率;不正之处欢迎批评指正。     线程的生命周期可以分为5...
    99+
    2023-01-31
    线程 进程 Python
  • Python:线程、进程与协程(3)——
        Queue模块是提供队列操作的模块,队列是线程间最常用的交换数据的形式。该模块提供了三种队列:Queue.Queue(maxsize):先进先出,maxsize是队列的大小,其值为非正数时为无线循环队列Queue.LifoQueue...
    99+
    2023-01-31
    线程 进程 Python
  • Python:线程、进程与协程(2)—
        上一篇博文介绍了Python中线程、进程与协程的基本概念,通过这几天的学习总结,下面来讲讲Python的threading模块。首先来看看threading模块有哪些方法和类吧。主要有:Thread :线程类,这是用的最多的一个类,...
    99+
    2023-01-31
    线程 进程 Python
  • Python:线程、进程与协程(1)——
            最近的业余时间主要放在了学习Python线程、进程和协程里,第一次用python的多线程和多进程是在两个月前,当时只是简单的看了几篇博文然后就跟着用,没有仔细去研究,第一次用的感觉它们其实挺简单的,最近这段时间通过看书, 看...
    99+
    2023-01-31
    线程 进程 Python
  • Python:线程、进程与协程(6)——
        上篇博文介绍了multiprocessing模块的内存共享(点击此处可以参看),下面讲进程池。有些情况下,所要完成的工作可以上篇博文介绍了multiprocessing模块的内存共享,下面讲进程池。有些情况下,所要完成的工作可以分解...
    99+
    2023-01-31
    线程 进程 Python
  • Python与协程从Python2—Py
    协程,又称微线程、纤程,英文名Coroutine;用一句话说明什么是线程的话:协程是一种用户态的轻量级线程。 Python对于协程的支持在python2中还比较简单,但是也有可以使用的第三方库,在python3中开始全面支持,也成为pyt...
    99+
    2023-01-31
    Python Py
  • 【PYTHON模块】:协程与greenl
    协程:又称为微线程,英文名称Coroutine。作用:它拥有自己的寄存器上下文和栈,能保留上一次调用时的状态,可以随时暂停程序,随时切换回来。优点:    •无需线程上下文切换的开销    •无需原子操作锁定及同步的开销      •方便切...
    99+
    2023-01-31
    模块 PYTHON greenl
  • python协程
    目录 python协程入门 函数的执行顺序 协程概念 总结 python协程入门 函...
    99+
    2023-01-30
    python 协程
  • python 协程
    进程和线程都会的切换都要消耗时间,保存线程进程当前状态以便下次继续执行。在不怎么需要cpu的程序中,即相对于IO密集型的程序,协程相对于线程进程资源消耗更小,切换更快,更适用于IO密集型。协程也是单线程的,没法利用cpu的多核,想利用cp...
    99+
    2023-01-30
    python 协程
  • Go语言中协程和线程的对比分析
    Go语言协程(Goroutine)与线程(Thread)是并发编程中常见的两种概念,它们都可以用来处理并发任务,但在实现方式、调度方式、资源消耗等方面有着显著的不同。本文将深入探讨Go...
    99+
    2024-02-25
    go语言 线程 协程
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作