行业资讯 2025年08月6日
0 收藏 0 点赞 501 浏览 4126 个字
摘要 :

文章目录 一、gevent库简介 二、gevent库的安装 三、gevent库的使用示例 (一)基本使用示例 (二)多协程切换示例 (三)基于gevent的Socket服务器示例(程序准确性待……




  • 一、gevent库简介
  • 二、gevent库的安装
  • 三、gevent库的使用示例
    • (一)基本使用示例
    • (二)多协程切换示例
    • (三)基于gevent的Socket服务器示例(程序准确性待检查)

    gevent库作为Python并发编程一个强大的工具,能帮助我们实现并发同步或异步编程。今天,咱们就深入了解一下gevent库的具体用法。

    一、gevent库简介

    gevent库的核心模式是Greenlet,它是一种以C扩展模块形式接入Python的轻量级协程。简单来说,Greenlet就像是一个个小任务,它们都在主程序所在的操作系统进程中运行,不过这些小任务之间是协作调度的,不会互相抢占资源,这样就能让程序在处理多个任务时更加高效。

    二、gevent库的安装

    在使用gevent库之前,需要先进行安装。在命令行中执行以下命令即可完成安装:

    pip install gevent
    

    执行这个命令后,系统会自动下载并安装gevent库及其相关依赖。在安装过程中,你可能会看到类似下面这样的输出信息,显示正在收集和安装各个相关的包:

    (emo is) C:\\Users187\\PycharmProjects\\myproject>pip install gevent
    collecting gevent
    Using cached gevent-21.12.0-cp37-cp37m-win_amd64.whl(1.6 MB) 
    Collecting zope.event
    Using cached zope.event-4.5.0-py2.py3-none-any.whl (6.8 kB)
    Requirement already satisfied: setuptools in d: \\programdata\\anaconda3\\envs\\emotional_analysis\\lib\\site-packages (from gevent)(49.6.0.post20200814) 
    collecting greenlet<2.0,>=1.1.0;platform_python_implementation==\"cpython\"
    Using cached greenlet-1.1.2-cp37-cp37m-win_amd64.whl (101 kB)
    Requirement already satisfied: cffi>=1.12.2;platform_python_implementation==\"cpython\" and sys_platform==\"win32\" in d:\\programdata\\anaconda3\\envs\\e es (from gevent)(1.14.3)
    Requirement already satisfied: zope.interface in d:\\programdata\\anaconda3\\envs\\emotional_analysis\\lib\\site-packages (from gevent)(5.4.0)
    

    三、gevent库的使用示例

    (一)基本使用示例

    下面通过一个简单的示例,来看看gevent库的基本用法:

    from gevent import monkey  # 为了能识别time模块的io
    
    monkey.patch_all()  # 必须放到被打补丁者的前面,如 time,socket 模块之前
    import gevent
    import time
    
    
    def gf(name):
        print(f\'{name}:我想打王者!!\')
        # gevent.sleep(2)
        time.sleep(2)
        print(f\'{name}:我想吃大餐!!!\')
    
    
    def bf(name):
        print(f\'{name}:一起打!!!\')
        # gevent.sleep(2)
        time.sleep(2)
        print(f\'{name}:一快去吃!!\')
    
    
    if __name__ == \"__main__\":
        start = time.time()
        # 创建协程对象
        g1 = gevent.spawn(gf, \'张三\')
        g2 = gevent.spawn(bf, \'李四\')
    
        # 开启任务
        g1.join()
        g2.join()
        end = time.time()
        print(end - start)
    

    在这段代码中:

    • monkey.patch_all()的作用是对一些标准库进行补丁操作,让gevent能够识别time模块这类标准库中的IO操作,实现协程的切换。这个操作需要放在导入其他可能被打补丁的模块(如timesocket等)之前。
    • 定义了两个函数gfbf,函数内部先打印一句话,然后通过time.sleep(2)模拟一个耗时操作。这里如果使用gevent.sleep(2),效果会更明显,它会让当前协程暂停2秒,同时允许其他协程执行,但这里为了体现gevent对标准库time.sleep的处理能力,使用了标准库的time.sleep
    • if __name__ == \"__main__\":代码块中,创建了两个协程对象g1g2,分别绑定gf函数和bf函数,并传入不同的参数。然后通过join方法来等待这两个协程执行完毕,最后计算并打印整个过程所花费的时间。
      运行这段代码,你会看到类似下面的输出结果:
    张三:我想打王者!!
    李四:一起打!!!
    张三:我想吃大餐!!!
    李四:一快去吃!!
    2.0309953689575195
    Process finished with exit code 0 
    

    从结果可以看出,两个协程是并发执行的,虽然每个函数内部都有2秒的等待时间,但总的执行时间大约是2秒,而不是4秒,这就体现了gevent库在并发处理上的优势。

    (二)多协程切换示例

    再来看一个更能体现协程切换的示例:

    import gevent
    
    
    def foo():
        print(\'Running in foo\')
        gevent.sleep(2)
        print(\'Explicit context switch to foo again\')
    
    
    def bar():
        print(\'Explicit context to bar\')
        gevent.sleep(2)
        print(\'Implicit context switch back to bar\')
    
    
    gevent.joinall([
        gevent.spawn(foo),
        gevent.spawn(bar),
    ])
    

    在这个示例中:

    • 定义了foobar两个函数,函数内部都使用了gevent.sleep(2)来模拟耗时操作。gevent.sleep会使当前协程暂停执行,将执行权交给其他可运行的协程。
    • 使用gevent.joinall方法来启动并等待foobar两个协程执行完毕。gevent.joinall接受一个协程对象列表作为参数,它会阻塞当前线程,直到列表中的所有协程都执行完成。
      运行这段代码,输出结果如下:
    Running in foo 
    Explicit context to bar 
    Explicit context switch to foo again 
    Implicit context switch back to bar
    Process finished with exit code 0
    

    从输出结果可以清晰地看到,在foo函数执行过程中,遇到gevent.sleep(2)时,程序会切换到bar函数执行,等bar函数执行到gevent.sleep(2)时,又会切换回foo函数继续执行,这就是协程的上下文切换过程。

    (三)基于gevent的Socket服务器示例(程序准确性待检查)

    下面是一个使用gevent实现的简单Socket服务器示例:

    from gevent import monkey, socket, pool
    
    monkey.patch_all()
    
    
    def server(port, pool):
        s = socket.socket()
        s.bind((\'0.0.0.0\', port))
        s.listen()
        while True:
            cli, addr = s.accept()
            print(\"Welcome %s to SocketServer\" % str(addr[0]))
            # 通过pool.spawn()运行协程
            pool.spawn(handle_request, cli)
    
    
    def handle_request(conn):
        try:
            data = conn.recv(1024)
            print(\"recv:\", data)
            data = \"From SockeServer:192.168.1.1---%s\" % data.decode(\"utf-8\")
            conn.sendall(bytes(data, encoding=\'utf-8\'))
            if not data:
                conn.shutdown(socket.SHUT_WR)
        except Exception as e:
            print(e)
        finally:
            conn.close()
    
    
    if __name__ == \'__main__\':
        # 限制并发协程数量为5
        pool = pool.Pool(5)
        server(80, pool)
    

    在这个示例中:

    • 同样使用monkey.patch_all()对相关模块进行补丁操作,确保gevent能够正常工作。
    • server函数创建了一个Socket服务器,绑定到本地的80端口并开始监听。每当有新的客户端连接时,它会打印欢迎信息,并通过pool.spawn方法启动一个新的协程来处理客户端请求,这里的pool是一个协程池,限制了并发协程的数量为5。
    • handle_request函数负责处理客户端的具体请求,接收客户端发送的数据,对数据进行简单处理后再发送回客户端。如果接收不到数据,就关闭连接。
    • if __name__ == \'__main__\':代码块中,创建了一个最大容纳5个协程的协程池pool,并启动了服务器。

    这个示例展示了gevent在网络编程中的应用,通过协程实现了高效的并发处理,不过需要注意的是,原文标注该程序准确性待检查,实际使用时可能需要进一步调试和优化。

    通过以上内容,相信你对gevent库的基本用法有了更深入的了解。在实际开发中,根据不同的需求合理运用gevent库,能够有效提升程序的性能和并发处理能力。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/10556.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号