python协程进阶,原来实现一个事件循环可以如此简单!

本文介绍了Python协程的概念,从生成器出发,讲解了事件循环的工作原理,如何处理协程中的阻塞,以及如何使用asyncio库进行异步编程。文中通过实例展示了Python协程的轻量级特性、自由切换和并发优势,并讨论了其在CPU密集型任务中的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

目前很多公司选择将python项目使用golang重构,很大一方面原因是因为golang的并发能力,golang自带的语法糖支持使并发编程变的相对简单,也更能充分的使用多核CPU的计算资源。

相应的,python长期受制于GIL,无法在多线程时使用多核CPU,所以一直以来在谈及python的缺陷时,性能总是无法回避的一个问题。当然,一些python著名的第三方组织也一直通过各种手段来改善python的并发性能,如twisted的异步模型使用事件驱动机制来提升python性能,著名的爬虫框架scrapy便是以twisted作为底层网络库来开发的,还有gevent,它使用greenlet在用户态完成栈和上下文切换来减少切换带来的性能损耗,同样还有著名的web协程框架tornado,他使用生成器来保存协程上下文及状态,使用原生的python语法实现了协程。但从python3.4开始python引入asyncio标准库,随后又在3.5引入async/await关键字,从根本上规范了python异步编程标准,使python异步编程逐渐流行起来。

关于什么是python协程,相信网上已经有了不少资料,但是只描述抽象的上层建筑难免会让人接受困难,本文希望可以通过从最简单的代码和逻辑,使用最基础的数据结构,从实现出发,带领大家理解什么是python协程。

首先需要补充一些基础知识

 

什么是生成器

我们都应该听说过迭代器,这在很多语言中都有类似的概念,简单的说,迭代器就是可以被迭代的对象,对其使用next操作可以返回一个元素,通常多次迭代后迭代器会中止,此时迭代器无法再使用。比如python中可以通过iter方法来将一个列表转换成迭代器:

I
n [1]: lst = [1, 2, 3]

In [2]: iterator = iter(lst)

In [3]: next(iterator)
Out[3]: 1

In [4]: next(iterator)
Out[4]: 2

In [5]: next(iterator)
Out[5]: 3

In [6]: next(iterator)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-7-4ce711c44abc> in <module>()
----> 1 next(iterator)

StopIteration:
进python群:835017344,获取python学习资料

生成器可以看作是迭代器的子类,同时提供了比迭代器更强大的功能,python中,可以使用yield关键字使函数返回生成器对象。

In [8]: def fun():
   ...:     yield 1
   ...:     yield 2
   ...:     yield 3
   ...:

In [9]: iterator = fun()

In [10]: next(iterator)
Out[10]: 1

In [11]: next(iterator)
Out[11]: 2

In [12]: next(iterator)
Out[12]: 3

In [13]: next(iterator)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-13-4ce711c44abc> in <module>()
----> 1 next(iterator)

StopIteration:

每次next调用, fun函数只执行四分之一,如果我们拥有多个生成器对象, 按照一定规则 可控的对他分别调用next,生成器每次的暂停都保存了执行进度和内部状态。如果将这三个生成器理解成协程,那不正是我们熟悉的协程间的切换?

事件循环

所以,我们可以想象,现在有一个循环和一个生成器列表,每次循环,我们都将所有的生成器进行一次调用,所有生成器交替执行。如下:

In [16]: gen_list = [fun(), fun(), fun()]

In [17]: while True:
    ...:     for gen in gen_list:
    ...:         print(next(gen))
    ...:
1
1
1
2
2
2
3
3
3
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-17-f2c1d557da
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值