• python基础知识整理 09-多任务:协程


    1 概念

    协程,又称微线程

    协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)

    通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

    协程和线程差异:

    • 线程的切换非常耗性能
    • 协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住

    2 协程-yield

    1. # -*- coding: utf-8 -*-
    2. import time
    3. def work1():
    4. while True:
    5. print("----work1---")
    6. yield
    7. time.sleep(0.5)
    8. def work2():
    9. while True:
    10. print("----work2---")
    11. yield
    12. time.sleep(0.5)
    13. def main():
    14. w1 = work1()
    15. w2 = work2()
    16. while True:
    17. next(w1)
    18. next(w2)
    19. if __name__ == "__main__":
    20. main()
    21. """
    22. ----work1---
    23. ----work2---
    24. ----work1---
    25. ----work2---
    26. ----work1---
    27. ----work2---
    28. ...
    29. """

    3 协程-greenlet

    使用pip install安装greenlet模块:  pip install greenlet

    1. # -*- coding: utf-8 -*-
    2. from greenlet import greenlet
    3. import time
    4. def test1():
    5. while True:
    6. print("---A--")
    7. gr2.switch()
    8. time.sleep(0.5)
    9. def test2():
    10. while True:
    11. print("---B--")
    12. gr1.switch()
    13. time.sleep(0.5)
    14. gr1 = greenlet(test1)
    15. gr2 = greenlet(test2)
    16. # 切换到gr1中运行
    17. gr1.switch()
    18. """
    19. ---A--
    20. ---B--
    21. ---A--
    22. ---B--
    23. ---A--
    24. ---B--
    25. ...
    26. """

    4 协程-gevent

    gevent比greenlet更强大,并且能够自动切换任务的模块

    其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

    由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

    安装: pip3 install gevent

    4.1 gevent的使用

    1. # -*- coding: utf-8 -*-
    2. import gevent
    3. def f(n):
    4. for i in range(n):
    5. print(gevent.getcurrent(), i)
    6. g1 = gevent.spawn(f, 5)
    7. g2 = gevent.spawn(f, 5)
    8. g3 = gevent.spawn(f, 5)
    9. g1.join()
    10. g2.join()
    11. g3.join()
    12. """
    13. <Greenlet "Greenlet-0" at 0x15233e9c378: f(5)> 0
    14. <Greenlet "Greenlet-0" at 0x15233e9c378: f(5)> 1
    15. <Greenlet "Greenlet-0" at 0x15233e9c378: f(5)> 2
    16. <Greenlet "Greenlet-0" at 0x15233e9c378: f(5)> 3
    17. <Greenlet "Greenlet-0" at 0x15233e9c378: f(5)> 4
    18. <Greenlet "Greenlet-1" at 0x15233e9c488: f(5)> 0
    19. <Greenlet "Greenlet-1" at 0x15233e9c488: f(5)> 1
    20. <Greenlet "Greenlet-1" at 0x15233e9c488: f(5)> 2
    21. <Greenlet "Greenlet-1" at 0x15233e9c488: f(5)> 3
    22. <Greenlet "Greenlet-1" at 0x15233e9c488: f(5)> 4
    23. <Greenlet "Greenlet-2" at 0x15233e9c598: f(5)> 0
    24. <Greenlet "Greenlet-2" at 0x15233e9c598: f(5)> 1
    25. <Greenlet "Greenlet-2" at 0x15233e9c598: f(5)> 2
    26. <Greenlet "Greenlet-2" at 0x15233e9c598: f(5)> 3
    27. <Greenlet "Greenlet-2" at 0x15233e9c598: f(5)> 4
    28. """

    可以看到,3个greenlet是依次运行而不是交替运行

    4.2 gevent切换执行

    1. # -*- coding: utf-8 -*-
    2. import gevent
    3. def f(n):
    4. for i in range(n):
    5. print(gevent.getcurrent(), i)
    6. # 用来模拟一个耗时操作,注意不是time模块中的sleep
    7. gevent.sleep(1)
    8. g1 = gevent.spawn(f, 5)
    9. g2 = gevent.spawn(f, 5)
    10. g3 = gevent.spawn(f, 5)
    11. g1.join()
    12. g2.join()
    13. g3.join()
    14. """
    15. <Greenlet "Greenlet-0" at 0x28fa86cc488: f(5)> 0
    16. <Greenlet "Greenlet-1" at 0x28fa86cc378: f(5)> 0
    17. <Greenlet "Greenlet-2" at 0x28fa86cc598: f(5)> 0
    18. <Greenlet "Greenlet-0" at 0x28fa86cc488: f(5)> 1
    19. <Greenlet "Greenlet-1" at 0x28fa86cc378: f(5)> 1
    20. <Greenlet "Greenlet-2" at 0x28fa86cc598: f(5)> 1
    21. <Greenlet "Greenlet-0" at 0x28fa86cc488: f(5)> 2
    22. <Greenlet "Greenlet-1" at 0x28fa86cc378: f(5)> 2
    23. <Greenlet "Greenlet-2" at 0x28fa86cc598: f(5)> 2
    24. <Greenlet "Greenlet-0" at 0x28fa86cc488: f(5)> 3
    25. <Greenlet "Greenlet-1" at 0x28fa86cc378: f(5)> 3
    26. <Greenlet "Greenlet-2" at 0x28fa86cc598: f(5)> 3
    27. <Greenlet "Greenlet-0" at 0x28fa86cc488: f(5)> 4
    28. <Greenlet "Greenlet-1" at 0x28fa86cc378: f(5)> 4
    29. <Greenlet "Greenlet-2" at 0x28fa86cc598: f(5)> 4
    30. """

    4.3 给程序打补丁

    1. # -*- coding: utf-8 -*-
    2. from gevent import monkey
    3. import gevent
    4. import random
    5. import time
    6. def coroutine_work(coroutine_name):
    7. for i in range(10):
    8. print(coroutine_name, i)
    9. time.sleep(random.random())
    10. gevent.joinall([
    11. gevent.spawn(coroutine_work, "work1"),
    12. gevent.spawn(coroutine_work, "work2")
    13. ])
    14. """
    15. work1 0
    16. work1 1
    17. work1 2
    18. work1 3
    19. work1 4
    20. work1 5
    21. work1 6
    22. work1 7
    23. work1 8
    24. work1 9
    25. work2 0
    26. work2 1
    27. work2 2
    28. work2 3
    29. work2 4
    30. work2 5
    31. work2 6
    32. work2 7
    33. work2 8
    34. work2 9
    35. """
    1. # -*- coding: utf-8 -*-
    2. from gevent import monkey
    3. import gevent
    4. import random
    5. import time
    6. # 有耗时操作时需要
    7. monkey.patch_all() # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
    8. def coroutine_work(coroutine_name):
    9. for i in range(10):
    10. print(coroutine_name, i)
    11. time.sleep(random.random())
    12. gevent.joinall([
    13. gevent.spawn(coroutine_work, "work1"),
    14. gevent.spawn(coroutine_work, "work2")
    15. ])
    16. """
    17. work1 0
    18. work2 0
    19. work2 1
    20. work2 2
    21. work2 3
    22. work1 1
    23. work2 4
    24. work1 2
    25. work2 5
    26. work2 6
    27. work1 3
    28. work2 7
    29. work1 4
    30. work2 8
    31. work1 5
    32. work2 9
    33. work1 6
    34. work1 7
    35. work1 8
    36. work1 9
    37. """

  • 相关阅读:
    Godot 4.0 加载为占位符(InstancePlaceholder)的用法和特点
    2022年 中国政企机构 网络安全 形势分析
    hough变换
    Python 生成器 (通俗讲解)
    公私域高效联动促进宠粮业务增长,Linkflow成功签约比瑞吉!
    使用 cmux smux 对 TCP 进行复用
    java计算机毕业设计房屋租赁网站源码+mysql数据库+系统+lw文档+部署
    Git——分布式版本控制工具
    自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战
    【情态动词练习题】Can / Could you
  • 原文地址:https://blog.csdn.net/bnever/article/details/125599238