[Python] 浅谈对Python协程的理解

浅谈对Python协程的理解

Python的协程也算是一个很重要的知识点了,我从刚刚开始的懵懵懂懂一知半解,到后面翻了很多书之后算是贯通一些了,因此我在此谈谈个人对Python协程的理解。

对比了《Python高级编程》、《流畅的Python》等书对协程的描写,我总结了以下看法:

1. 你的底层库函数必须是异步的、不IO阻塞的

首先,要想实现协程,你的底层协程函数必须是异步的、不IO阻塞的。这句话很关键,你要确保你底层的协程不是IO阻塞的,能通过 yield from 交出控制权给调度程序,同时还要在IO操作完成时能够触发一个信号,告诉调度程序你IO结束了。 这个信号就类似于嵌入式系统的中断机制,当一个任务的外部IO操作完成了,IO控制器就会产生一个中断信号,CPU接收中断信号,就可以继续调度运行该任务,也或许是将该任务加入就绪队列,待会儿再执行调度。协程也大致是这样的一个思路。也就是说,最内层的子生成器是库中真正执行I/O操作的函数,而不是我们自己编写的函数。

就目前来看,Python的协程,大多是用asyncio、Twisted、 Tornado、gevent 这些库/模块。至于 asyncio,《流畅的Python》中有描述:

使用asyncio包时,我们编写的异步代码中包含由asyncio本身驱动的协程(即委派生成器),而生成器最终把职责委托给asyncio包或第三方库(如aiohttp)中的协程。这种处理方式相当于架起了管道,让asyncio事件循环(通过我们编写的协程)驱动执行低层异步I/O操作的库函数。

概括起来,这些库之所以能够实现协程,是因为“驱动执行低层异步I/O操作的库函数”。而能“执行低层异步I/O操作的库函数”,我们一般是没办法实现的(就我目前还不会实现……乖乖使用这些库函数)。

2. 一入协程,所有协程。

简单来说,如果你用了协程,为了尽量提高性能,所有的函数应该能执行异步操作,否则很容易阻塞事件循环。比如,除非想阻塞主线程,从而冻结事件循环或整个应用,否则不要在 asyncio 协程中使用 time.sleep(…)。如果协程需要在一段时间内什么也不做,应该使用 yield from asyncio.sleep(DELAY)。

3. 使用其他线程处理阻塞

在第2点的前提下,尽量避免阻塞事件循环的唯一线程,如果你意识到了某一调用是会阻塞的,比如访问本地文件系统,那么你可以把这个调用放在其他线程中跑,因为阻塞型I/O调用在背后会释放GIL,因此另一个线程可以继续,这也就意味着事件循环所在的线程被阻塞的概率就大大降低了。比如可以使用事件循环对象的run_in_executor方法处理阻塞型调用。

asyncio的事件循环在背后维护着一个ThreadPoolExecutor对象,我们可以调用run_in_executor方法,把可调用的对象发给它执行。

协程和多线程的区别要点

  • 线程不受控制。如果使用线程做过重要的编程,你就知道写出程序有多么困难,因为调度程序任何时候都能中断线程。你无法知道CPU当前执行的是哪个线程,因此必须记住保留锁,去保护程序中的重要部分,防止多步操作在执行的过程中中断,防止数据处于无效状态。

  • 而协程能够安全取消。协程默认会做好全方位保护,以防止中断。我们必须显式产出才能让程序的余下部分运行。对协程来说,无需保留锁,协程自身就会同步,因为在任意时刻只有一个协程运行。想交出控制权时,可以使用yield或yield from把控制权交还调度程序。协程能在暂停的yield处取消,因此可以处理CancelledError异常,执行清理操作。这就是能够安全地取消协程的原因。

杂谈

话外题,2020年12月出了一本书写Twisted的,叫《精通Twisted:Python事件驱动及异步编程》。对于想深入学习Twisted的人来说,看着还蛮诱人的。里面也介绍了 Django 3.0 支持异步的特性。

尽管线程版和asyncio版HTTP客户端的下载总时间相差无几,但是asyncio版发送请求的速度更快,因此很有可能对服务器发起DoS攻击。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值