• Python之协程


    协程

      协程是程序员创造出来的不真实的一个东西

        协程也可以称之为微线程,就是程序员可以人为的控制代码的运行的顺序(来回切换),其实就是对线程进行分片,使起代码来回切换

     在线程中来回切换的实例

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import greenlet
     5 
     6 
     7 def testone():
     8     print(11)
     9     gr2.switch()
    10     print(22)
    11     gr2.switch()
    12 
    13 
    14 def testtwo():
    15     print(33)
    16     gr1.switch()
    17     print(44)
    18 
    19 
    20 # 创建两个协程
    21 gr1 = greenlet.greenlet(testone)
    22 gr2 = greenlet.greenlet(testtwo)
    23 
    24 gr1.switch()
    25 # 单纯的协程没多大用  切换肯定还是存在时间的消耗

    协程存在的意义

      单纯的协程没多大用,就是遇到IO操作切换的时候就显得格外的牛逼,就有格局了

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 from gevent import monkey
     5 monkey.patch_all()  # 代码中遇到IO都会自动执行greenlet的switch进行切换
     6 import requests
     7 import gevent
     8 
     9 
    10 def get_page(url):
    11     ret = requests.get(url)
    12     print(url, ret.content.decode('utf8'))
    13 
    14 
    15 gevent.joinall([
    16     gevent.spawn(get_page, 'https://www.python.org/'),  # 协程1
    17     gevent.spawn(get_page, 'https://www.yahoo.com/'),   # 2
    18     gevent.spawn(get_page, 'https://github.com/'),      # 3
    19 ])

    总结:**********

    1.什么是协程:
      称之为微线程,开发者控制线程执行流程,控制先执行某段代码然后再切换到另外的函数执行。协程本身是由程序员创造出的一个不真实存在的东西
    2.协程可以提高并发吗?
      协程本身是无法实现并发 协程+io切换性能就能提高
    3.进程 线程 协程区别?
      一个应用程序就是一块软件,一块软件中可以有多个进程,进程就是计算机分配资源的最小单元,主要用来做数据隔离,一个进程中至少存在一个线程(这个线程就是这个进程中的主线程),而线程就是CPU最小工作单元,真正用来工作的就是线程,但是呢在应用场景下:在其他语言中可能基本没咋提进程这个概念,他们基本用的线程,在python中呢有那么一说就是一般io密集型操作用多线程,计算密集型呢就用多进程,其实就是Python内部加了一把GIL锁,就是一个进程中同一时刻只允许一个线程被CPU调度,如果想利用CPU的多核优势,只能开进程,所以呢只有计算密集型才适合开进程,开多线程没用,而io密集型就要开线程,因为io操作不占CPU,程序员这个级别越来越牛逼嘛就创建了协程,这个协程本身就是不存在的东西,协程本身由程序员人为来控制代码块进行切换,本身存在没大多意义,如果协程遇到io切换了就非常牛逼了,遇到io操作就可以干其它的事情,相当于一个线程被分片了,所达到的效果就是这个线程一直没有停一直都在工作 ,这些就是这几个东西的本质上的区别,然后呢Python中协程有个greenlet模块就是可以进行代码块的切换这个模块,实现协程+io自动操作就是用的gevent这个模块,其实这个gevent这个模块也用到了greenlet这个模块,它里边有个monkey.patch_all()方法在这里就是遇到IO自动就会采用greenlet去自动的切换,gevent里边对源生的socket/select/threading/subprocess等等一些列的封装大概这三者之间的区别。想了解gevent自己看源码。

    还有个简单的例子就是利用生成器关键字yield实现

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 
     5 def f1():
     6     print(11)
     7     x1 = yield 1
     8     print(x1, 22)
     9     x2 = yield 2
    10     print(x2, 33)
    11 
    12 
    13 def f2():
    14     print(55)
    15     yield
    16     print(66)
    17     yield
    18     print(77)
    19 
    20 
    21 v1 = f1()
    22 v2 = f2()
    23 # next(v1)
    24 # v1.__next__()
    25 r1 = v1.send(None)  # 11
    26 print(r1)  # 1
    27 r2 = v1.send(999)  # x1=999   999 22
    28 print(r2)  # 2







  • 相关阅读:
    转帖:linux 下注册apache开机自启动
    apache 编译 rewrite 模块
    Skyline开发入门(C#)
    matlab的m文件怎么集成到vs里?
    C#打包安装与卸载
    OnClick与OnClientClick的时序和条件
    javascript弹出窗口代码大全
    .NET开发人员必知的八个网站
    [转] GIS算法源码集合
    最短路径算法——Dijkstra and Floyd算法
  • 原文地址:https://www.cnblogs.com/Alexephor/p/11234327.html
Copyright © 2020-2023  润新知