Generator(生成器),入门初基,Coroutine(原生协程),登峰造极,Python3.10并发异步编程async底层实现

yizhihongxing

普遍意义上讲,生成器是一种特殊的迭代器,它可以在执行过程中暂停并在恢复执行时保留它的状态。而协程,则可以让一个函数在执行过程中暂停并在恢复执行时保留它的状态,在Python3.10中,原生协程的实现手段,就是生成器,或者说的更具体一些:协程就是一种特殊的生成器,而生成器,就是协程的入门心法。

协程底层实现

我们知道,Python3.10中可以使用async和await关键字来实现原生协程函数的定义和调度,但其实,我们也可以利用生成器达到协程的效果,生成器函数和普通函数的区别在于,生成器函数使用 yield 语句来暂停执行并返回结果。例如,下面是一个使用生成器函数实现的简单协程:

def my_coroutine():  
    while True:  
        x = yield  
        print(x)  
  
# 使用生成器函数创建协程  
coroutine = my_coroutine()  
  
# 启动协程  
next(coroutine)  
  
# 在协程中传入数据  
coroutine.send(1)  
coroutine.send(2)  
coroutine.send(3)

程序返回:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/test.py"  
1  
2  
3

在上面的代码中,生成器函数 my_coroutine 使用了一个无限循环来实现协程的逻辑。每当调用 send 方法时,协程就会从 yield 语句处恢复执行,并将传入的参数赋值给变量 x。

如此,就完成了协程执行-》阻塞-》切换-》回调的工作流模式。

当然,作为事件循环机制,协程服务启动可能无限期地运行,要关闭协程服务,可以使用生成器的close()方法。当一个协程被关闭时,它会生成GeneratorExit异常,该异常可以用生成器的方式进行捕获:

def my_coroutine():  
    try :  
        while True:  
            x = yield  
            print(x)  
    except GeneratorExit:  
            print("协程关闭")  
  
# 使用生成器函数创建协程  
coroutine = my_coroutine()  
  
# 启动协程  
next(coroutine)  
  
# 在协程中传入数据  
coroutine.send(1)  
coroutine.send(2)  
coroutine.send(3)  
  
coroutine.close()

程序返回:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/test.py"  
1  
2  
3  
协程关闭

业务场景

在实际业务场景中,我们也可以使用生成器来模拟协程流程,主要体现在数据的IO流操作中,假设我们需要从本地往服务器传输数据,首先建立链接对象:

class Connection:  
  
  
    def __init__(self, addr):  
        self.addr = addr  
  
    def transmit(self, data):  
        print(f"X: {data[0]}, Y: {data[1]} sent to {self.addr}")

随后建立生成器函数:

def send_to_server(conn):  
    while True:  
        try:  
            raw_data = yield  
            raw_data = raw_data.split(' ')  
            coords = (float(raw_data[0]), float(raw_data[1]))  
            conn.transmit(coords)  
        except ConnectionError:  
            print("链接丢失,进行回调")  
            conn = Connection("重新连接v3u.cn")

利用生成器调用链接类的transmit方法进行数据的模拟传输,如果链接断开,则会触发回调重新连接,执行逻辑:

if __name__ == '__main__':  
  
  
    conn = Connection("v3u.cn")  
  
    sender = send_to_server(conn)  
    sender.send(None)  
  
    for i in range(1, 6):  
        sender.send(f"{100/i} {200/i}")  
  
    # 模拟链接断开  
    conn.addr = None  
  
  
    sender.throw(ConnectionError)   
  
    for i in range(1, 6):  
        sender.send(f"{100/i} {200/i}")

程序返回:

X: 100.0, Y: 200.0 sent to v3u.cn  
X: 50.0, Y: 100.0 sent to v3u.cn  
X: 33.333333333333336, Y: 66.66666666666667 sent to v3u.cn  
X: 25.0, Y: 50.0 sent to v3u.cn  
X: 20.0, Y: 40.0 sent to v3u.cn  
链接丢失,进行回调  
X: 100.0, Y: 200.0 sent to 重新连接v3u.cn  
X: 50.0, Y: 100.0 sent to 重新连接v3u.cn  
X: 33.333333333333336, Y: 66.66666666666667 sent to 重新连接v3u.cn  
X: 25.0, Y: 50.0 sent to 重新连接v3u.cn  
X: 20.0, Y: 40.0 sent to 重新连接v3u.cn

如此,我们就可以利用生成器的“状态保留”机制来控制网络链接突然断开的回调补救措施了。

所以说,协程就是一种特殊的生成器:

async def test():  
    pass  
  
print(type(test())) 

您猜怎么着?

<class 'coroutine'>

结语

诚然,生成器和协程也并非完全是一个概念,与生成器不同的是,协程可以被另一个函数(称为调用方)恢复执行,而不是只能由生成器本身恢复执行。这使得协程可以用来实现更复杂的控制流,因为它们可以在执行时暂停并在任意时刻恢复执行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Generator(生成器),入门初基,Coroutine(原生协程),登峰造极,Python3.10并发异步编程async底层实现 - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • 影片自由,丝滑流畅,Docker容器基于WebDav协议通过Alist挂载(百度网盘/阿里云盘)Python3.10接入

    使用过NAS(Network Attached Storage)的朋友都知道,它可以通过局域网将本地硬盘转换为局域网内的“网盘”,简单理解就是搭建自己的“私有云”,但是硬件和网络成本都太高了,有点可望而不可及的意思。Alist开源库则可以满足我们,它能将公共网盘反过来变成一种联网的本地硬盘,使用Web页面来统一挂载和管理,网盘类型包含但不限于:百度网盘、阿里…

    2023年3月31日
    00
  • Python3.10动态修改Windows系统(win10/win11)本地IP地址(静态IP)

    一般情况下,局域网里的终端比如本地服务器设置静态IP的好处是可以有效减少网络连接时间,原因是过程中省略了每次联网后从DHCP服务器获取IP地址的流程,缺点是容易引发IP地址的冲突,当然,还有操作层面的繁琐,如果想要切换静态IP地址,就得去网络连接设置中手动操作,本次我们使用Python3.10动态地修改电脑的静态IP地址。 获取多网卡配置 一个网卡对应一个静…

    python 2023年5月9日
    00
  • 极速进化,光速转录,C++版本人工智能实时语音转文字(字幕/语音识别)Whisper.cpp实践

    业界良心OpenAI开源的Whisper模型是开源语音转文字领域的执牛耳者,白璧微瑕之处在于无法通过苹果M芯片优化转录效率,Whisper.cpp 则是 Whisper 模型的 C/C++ 移植版本,它具有无依赖项、内存使用量低等特点,重要的是增加了 Core ML 支持,完美适配苹果M系列芯片。 Whisper.cpp的张量运算符针对苹果M芯片的 CPU …

    人工智能概论 2023年5月4日
    00
  • 旧酒换新瓶,新版M1/M2芯片Macos(Ventura)安装古早版本Python2.7(Python2.x)

    向下兼容特性是软件开发系统的一个重要指标,它是指一个新的系统或者软件能够与旧的系统或软件兼容并正常运行。这意味着旧系统或软件可以在新系统或软件中使用,而不会出现问题。向下兼容对于提高软件或系统的可用性非常重要,因为它允许用户在不更换旧系统或软件的情况下使用新系统或软件。 我们知道MacOS系统从Monterey12.3版本起就移除了系统内置的Python2,…

    Python开发 2023年3月31日
    00
  • 把盏言欢,款款而谈,ChatGPT结合钉钉机器人(outgoing回调)打造人工智能群聊/单聊场景,基于Python3.10

    就像黑火药时代里突然诞生的核弹一样,OpenAI的ChatGPT语言模型的横空出世,是人工智能技术发展史上的一个重要里程碑。这是一款无与伦比、超凡绝伦的模型,能够进行自然语言推理和对话,并且具有出色的语言生成能力。 好吧,本篇的开头其实是由ChatGPT生成的: 没办法,面对这个远超时代的AI产品,我们能说什么呢?顶礼膜拜?惊为天人?任何言语对于描述Chat…

    2023年4月2日
    00
  • 加密,各种加密,耙梳加密算法(Encryption)种类以及开发场景中的运用(Python3.10)

    不用说火爆一时,全网热议的Web3.0区块链技术,也不必说诸如微信支付、支付宝支付等人们几乎每天都要使用的线上支付业务,单是一个简简单单的注册/登录功能,也和加密技术脱不了干系,本次我们耙梳各种经典的加密算法,试图描摹加密算法在开发场景中的运用技巧。 可逆加密算法(对称加密) 加密算法是一种将原始数据转换为加密数据的方法。根据加密算法的不同特征,可以将其分为…

    2023年3月31日
    00
  • 玫瑰花变蚊子血,自动化无痕浏览器对比测试,新贵PlayWright Vs 老牌Selenium,基于Python3.10

    也许每一个男子全都有过这样的两个女人,至少两个。娶了红玫瑰,久而久之,红的变了墙上的一抹蚊子血,白的还是床前明月光;娶了白玫瑰,白的便是衣服上沾的一粒饭黏子,红的却是心口上一颗朱砂痣。–张爱玲《红玫瑰与白玫瑰》 Selenium一直都是Python开源自动化浏览器工具的王者,但这两年微软开源的PlayWright异军突起,后来者居上,隐隐然有撼动Selen…

    2023年3月31日
    00
  • 乾坤大挪移,如何将同步阻塞(sync)三方库包转换为异步非阻塞(async)模式?Python3.10实现。

    众所周知,异步并发编程可以帮助程序更好地处理阻塞操作,比如网络 IO 操作或文件 IO 操作,避免因等待这些操作完成而导致程序卡住的情况。云存储文件传输场景正好包含网络 IO 操作和文件 IO 操作,比如业内相对著名的七牛云存储,官方sdk的默认阻塞传输模式虽然差强人意,但未免有些循规蹈矩,不够锐意创新。在全球同性交友网站Github上找了一圈,也没有找到异…

    Python开发 2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部