zoukankan      html  css  js  c++  java
  • Day 42 协程. IO 并发

    一、什么是协程?

    是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

    协程相比于线程切换效率更快了.

    本质是线程

    能够在多个任务之间切换来节省一些IO时间.

    协程中任务之间的切换时间开销要远远小于进程线程之间的切换.

    真正的协程模块就是使用greenlet完成切换的.

    进程和协程的任务切换由操作系统完成.

    协程任务之间的切换由程序完成.

     协程任务之间的切换由程序代码完成 , 只有遇到协程模块能识别的io操作的时候程序才会进行任务切换,实现并发的效果。

    协程: 

    能够在一个线程中实现并发效果的概念.

    能够规避一些任务中的IO操作.

    在任务的执行过程中,检测到IO就切换到其他任务.

    在两个任务之间来回切换数据(简单的协程的概念)

    # import time
    # def consumer():
    #     while True:
    #         x = yield
    #         time.sleep(1)
    #         print('处理了数据 :',x)
    #
    # def producer():
    #     c = consumer()#生成一个生成器对象
    # next(c) #每次next返回一个值
    # for i in range(10):
    # time.sleep(1)
    # print('生产了数据 :',i)
    # c.send(i)
    # producer()

    输出结果:虽然实现了切换,但是没有节约IO时间.

    D:PycharmProjects	estvenvScriptspython.exe D:/parcharm/42.py
    生产了数据 : 0
    处理了数据 : 0
    生产了数据 : 1
    处理了数据 : 1
    生产了数据 : 2
    处理了数据 : 2
    生产了数据 : 3
    处理了数据 : 3
    生产了数据 : 4
    处理了数据 : 4
    生产了数据 : 5
    处理了数据 : 5
    生产了数据 : 6
    处理了数据 : 6
    生产了数据 : 7
    处理了数据 : 7
    生产了数据 : 8
    处理了数据 : 8
    生产了数据 : 9
    处理了数据 : 9
    

    二 、安装 gevent和greenlet

     查看安装状态

     

     真正的协程模块就是使用greenlet完成的切换

    from greenlet import  greenlet
    def eat():
        print("吃开始")
        g2.switch()
        print("吃完了")
        g2.switch()
    def play():
        print("开始玩")
        g1.switch()
        print('玩完了')
    g1 =greenlet(eat)
    g2 =greenlet(play)
    g1.switch()
    

      打印结果:

    D:PycharmProjects	estvenvScriptspython.exe D:/parcharm/44.py
    吃开始
    开始玩
    吃完了
    玩完了
    

      

    协程能够在一个线程中实现并发效果的概念。

      能够规避一些任务中的IO操作

      在任务的执行过程中,检测到IO就切换到其他的任务.

    三、爬虫的例子(正则有基础.)

    请求过程中的IO等待

    import requests #需要pip安装的。
    from urllib.request import urlopen#内置的模块
    url='http://www.baidu.com'
    res1 =urlopen(url)
    res2 = requests.get(url)
    print(res1)
    print(res2)
    
    print(res1.read().decode('utf-8'))# 有格式的
    print(res2.content.decode('utf-8'))#无格式的。
    

      

    爬虫 (结果是一起显示出来的。)

    gevent 用在爬虫和socket的编程中会用的到.

    gevent是python的一个并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效.而且其中有个monkey类,

    将现有基于Python线程直接转化为greenlet(类似于打patch).他和线程框架性能比高大概4倍(看下图,是gevent和paste的对比):

    from gevent import  monkey;monkey.patch_all()
    import gevent
    from urllib.request import urlopen
    def get_url(url):
        response = urlopen(url)
        content = response.read().decode('utf-8')
        return len(content)
    
    g1 =gevent.spawn(get_url,'http://www.baidu.com')
    g2 =gevent.spawn(get_url,'http://www.sohu.com')
    g3 =gevent.spawn(get_url,'http://www.hao123.com')
    g4 =gevent.spawn(get_url,'http://www.cnblog.com')
    g5 =gevent.spawn(get_url,'http://www.cnblog.com')
    gevent.joinall([g1,g2,g3,g4,g5])
    print(g1.value)
    print(g2.value)
    print(g3.value)
    print(g4.value)
    print(g5.value)
    

      打印结果

    D:PycharmProjects	estvenvScriptspython.exe D:/parcharm/44.py
    114439
    185037
    523375
    1887
    1887
    

    协程实现socket的案例

    协程间的切换是代码级别的, 

    线程间切换时操作系统级别的。

     Server端

    from gevent import monkey;monkey.patch_all()
    import socket
    import gevent
    def talk(conn):
        conn.send(b'hello')
        print(conn.recv(1024).decode('utf-8'))
        conn.close()
    
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    while True:
        conn,addr = sk.accept()
        gevent.spawn(talk,conn)
    sk.close()
    

      client端

    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    print(sk.recv(1024))
    msg = input('>>>').encode('utf-8')
    sk.send(msg)
    sk.close()
    

      

    四 IO模型.

    blocking IO 阻塞IO 

    nonblocking IO 非阻塞IO 

    IO multiplexing  IO 多路复用

    asynchronous IO 异步 IO

    Blocking IO 阻塞IO

    同步:同步提交一个任务之后要等待这个任务执行完毕.

    异步只管提交任务,

      

     

     

  • 相关阅读:
    第十一周项目6-回文&素数(一)
    第十一周项目1-函数版星号图(三) .
    囚徒困境 For BBasic
    第十一周项目5-当年第几天
    第十一周项目4-特殊三位数
    第十一周项目3-程序的多文件组织
    第十一周项目2-求最大公约数
    第十一周项目1-函数版星号图(二)
    第十一周项目1-函数版星号图(一)
    第十周-囚徒困境
  • 原文地址:https://www.cnblogs.com/mengbin0546/p/8696491.html
Copyright © 2011-2022 走看看