zoukankan      html  css  js  c++  java
  • 协程greenlet、gevent

    greenlet
    为了更好使用协程来完成多任务,python中greenlet模块对其封装,从而使得切换任务变得更加简单
    安装方式

    pip3 install greenlet

    示例代码:

    from greenlet import greenlet
    import time
    
    def test1():
    while True:
    print("-----真-----")
    gr2.switch()
    time.sleep(0.5)
    
    def test2():
    while True:
    print("-----真-----")
    gr1.switch()
    time.sleep(0.5)
    
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    
    # 切换到gr1中运行
    gr1.swith() 


    gevent
    greenlet已经实现了协程,但是这个工人切换,是不是觉得太麻烦了,不要着急,python还有一个比greenlet更强大的并且能够自动切换任务的模块`gevent`
    其原理是当一个greentlet遇到IO(指的是input ouput输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO完成,再适当的时候切换回来继续执行。

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

    安装

    pip3 install gevent 

    1.gevent的使用

    import gevent
    
    def f(n):
    for i in range(n):
      print(gevent.getcurrent(), i)
    g1
    = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

    运行结果 

    F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py
    <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 0
    <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 1
    <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 2
    <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 3
    <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 4
    <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 0
    <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 1
    <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 2
    <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 3
    <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 4
    <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 0
    <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 1
    <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 2
    <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 3
    <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 4
    
    Process finished with exit code 0

    gevent切换执行

    import gevent
    
    def f(n):
    for i in range(n):
      print(gevent.getcurrent(), i)
      # 用来模拟一个耗时操作,注意不是time模块中的sleep
      gevent.sleep(1)
    g1
    = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

    运行结果 

    F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py
    <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 0
    <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 0
    <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 0
    <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 1
    <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 1
    <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 1
    <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 2
    <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 2
    <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 2
    <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 3
    <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 3
    <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 3
    <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 4
    <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 4
    <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 4
    
    Process finished with exit code 0

    3. 给程序打补丁

    from gevent import monkey
    import gevent
    import random
    import time
    
    # 有耗时操作时需要
    monkey.patch_all() # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
    
    def coroutine_work(coroutine_name):
    for i in range(10):
    print(coroutine_name, i)
    time.sleep(random.random())
    
    gevent.joinall([
    gevent.spawn(coroutine_work, "work1"),
    gevent.spawn(coroutine_work, "work2")
    ])

    运行结果

    F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_test.py
    work1 0
    work2 0
    work2 1
    work1 1
    work1 2
    work1 3
    work2 2
    work1 4
    work1 5
    work2 3
    work1 6
    work1 7
    work2 4
    work2 5
    work1 8
    work1 9
    work2 6
    work2 7
    work2 8
    work2 9
    
    Process finished with exit code 0
  • 相关阅读:
    使用CORS解决flask前端页面跨域问题
    re.search 与 re.match的区别
    jupyter-notebook快捷键的使用
    docker端口的映射顺序
    [转]/dev/null 命令用法
    [转]Docker容器内不能联网的6种解决方案
    牛客网python试题-错误整理-20180711
    docker常用命令
    linux实用命令-待补充
    docker exec小脚本
  • 原文地址:https://www.cnblogs.com/colden/p/9763569.html
Copyright © 2011-2022 走看看