• Python 协程


    协程基础

    底层实现

    • 协程的底层是使用greenlet模块来实现的
    from greenlet import greenlet
    
    def func1():
        print("eat start")# 2
        g2.switch()
        print("eat end")# 4
        g2.switch()
    
    
    def func2():
        print("play start")# 3
        g1.switch()
        print("play end")# 5
    
    
    g1 = greenlet(func1)
    g2 = greenlet(func2)
    g1.switch()# 1
    

    介绍

    • 当遇到IO操作时将程序切换到其他函数继续执行会提高CPU的利用效率
    • 一个线程可以开启500个协程
    • 更适用于网络操作中

    安装

    pip install gevent
    

    应用

    协程实现

    from gevent import monkey;monkey.patch_all()
    # 将下面导入的所有的包中的阻塞操作封装成gevent可以识别的阻塞
    # 没有这行代码time.sleep语句是不被gevent识别的
    # 使用gevent一定要将这一行代码放到开头
    import time
    import gevent
    
    def func1():
        print("eat start")
        time.sleep(1)# 阻塞
        print("eat end")
    
    
    
    def func2():
        print("play start")
        time.sleep(1)# 阻塞
        print("play end")
    
    g1 = gevent.spawn(func1)# 创建协程
    g2 = gevent.spawn(func2)
    g1.join() # 等待协程g1结束
    g2.join() # 等待协程g2结束
    # gevent可以自动调度协程,实现在遇到IO操作时自动切换
    

    协程爬虫

    from gevent import monkey;monkey.patch_all()# 感知其他包中的阻塞
    import requests
    import gevent
    
    def geturl(url):
        rep = requests.get(url)
        print(url,len(rep.text))
    
    
    g1 = gevent.spawn(geturl,"https://www.baidu.com")# 创建协程
    g2 = gevent.spawn(geturl,"https://www.iqiyi.com")
    g3 = gevent.spawn(geturl,"https://www.taobao.com")
    g4 = gevent.spawn(geturl,"https://www.sohu.com")
    
    gevent.joinall([g1,g2,g3,g4])# 将全部协程join与主程序同步,接收的是可迭代对象
    # 同步的原因:异步执行同步接收结果,如果不同步则主程序直接执行完毕接收不到结果
    

    协程实现socket并发

    server

    from gevent import monkey;monkey.patch_all()
    import socket
    import gevent
    def func(conn):
    
        conn.send(b"hello")
        print(conn.recv(1024).decode("utf8"))
        conn.close()
    sk = socket.socket()
    sk.bind(("127.0.0.1",8080))
    sk.listen()
    g_list = []
    while True:
        conn, addr = sk.accept()
        g = gevent.spawn(func,conn)
        g_list.append(g)
    
    
    
    sk.close()
    

    client

    import socket
    sk = socket.socket()
    sk.connect(("127.0.0.1",8080))
    print(sk.recv(1024).decode("utf8"))
    msg = input(">>>").encode("utf8")
    sk.send(msg)
    
  • 相关阅读:
    内存映射的原理
    Intel 面试(就不该报外企,英语是硬伤)
    基于多进程和基于多线程服务器的优缺点及nginx服务器的启动过程
    pdflush机制
    百度面试
    同步IO和异步IO的区别
    阿里面试
    linux内核学习之四:进程切换简述
    static成员函数不能调用non-static成员函数
    C/C++函数调用方式
  • 原文地址:https://www.cnblogs.com/changjiangwei/p/11879111.html
Copyright © 2020-2023  润新知