zoukankan      html  css  js  c++  java
  • python生成器和使用gevent操作协程

    python中的生成器是一种特殊的迭代器,可以类比成类:

    如下定义斐波那契数列,初始化obj1,相当于new 出一个对象

    以下两种方式输出结果相同,均为斐波那契数列前10项

    def fibonacci(all_num):
        a, b = 0, 1
        current_num = 0
        while current_num < all_num:
            yield a
            a, b = b, a + b
            current_num += 1
    obj1 = fibonacci(10)
    for ind in range(10):
        print(next(obj1))
    def fibonacci(all_num):
        a, b = 0, 1
        current_num = 0
        while current_num < all_num:
            yield a
            a, b = b, a + b
            current_num += 1
    obj1 = fibonacci(10)
    for obj in obj1:
        print(obj)

    其中yield关键字说明此函数为一个生成器,yield a可以作为一个返回值打断函数并返回结果,此为协程的雏形,如果定义两个生成器实例,两个生成器通过yield可以实现交替运行,即为协程

    看如下代码:

    def fibonacci(all_num,name):
        a, b = 0, 1
        current_num = 0
        while current_num < all_num:
            yield a
            print(name)
            a, b = b, a + b
            current_num += 1
    obj1 = fibonacci(10,"fib1")
    obj2 = fibonacci(10,"fib2")
    for ind in range(10):
        print(next(obj1))
        print(next(obj2))

    输出:

    这便实现了协程交替工作

    使用greenlet管理协程:

    使用greenlet的switch()方法替换yield

    from greenlet import greenlet
    
    def wh2():
        while True:
            print("---2---")
            gr1.switch()
            time.sleep(0.1)
    
    
    def wh1():
        while True:
            print("---1---")
            gr2.switch()
            time.sleep(0.1)
    
    
    gr1 = greenlet(wh1)
    gr2 = greenlet(wh2)
    gr1.switch()

    输出如下:

    使用最多最广泛的还是使用gevent管理协程:

    安装gevent

    pip install gevent

    def wh2():
    while True:
    print("---2---")
    time.sleep(0.1)


    def wh1():
    while True:
    print("---1---")
    time.sleep(0.1)

    def spawn():
    g1 = gevent.spawn(wh1)
    g2 = gevent.spawn(wh2)
    g1.join()
    g2.join()

    spawn()

    直接代码中去掉yield、switch,使用gevent.spawn()方法---下蛋

    但是输出如下:

    原因是我们需要把time.sleep()替换成gevent.sleep(),join也可以替换成joinall

    def wh2():
        while True:
            print("---2---")
            gevent.sleep(0.1)
    
    
    def wh1():
        while True:
            print("---1---")
            gevent.sleep(0.1)
    
    def spawn():
        g1 = gevent.spawn(wh1)
        g2 = gevent.spawn(wh2)
        gevent.joinall([g1,g2])
    
    spawn()

    如果不替换time.sleep(),我们也可以使用gevent的money模块全局替换:

    from gevent import monkey
    
    monkey.patch_all()

    输出如下:

    实现了协程工作,协程的开销是比线程还要小的,以上代码的sleep部分实际中可以去掉,因为在耗时部分gevent才会走其他的实例,为了方便测试才加上的,不然会直接不卡顿的for循环其中一个实例,如下的例子就是没有sleep代码的协程工作例子,由于网络通信比较耗时,所以协程会自动切换到另一个实例,好像是并发工作一样。

    协程demo:

    import gevent
    from gevent import monkey
    import urllib.request
    # 补丁 实现协同工作:看上去就像是多线程 monkey.patch_all() def download_img(name,url): req
    = urllib.request.urlopen(url) img_content = req.read() with open(name,"wb") as f: f.write(img_content) if __name__ == '__main__': gevent.joinall( [ gevent.spawn(download_img,"1.jpg","https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_match%2F0%2F12070081997%2F0.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1627992970&t=0a1f9c49767613a1f8ec792c975c3ae6"), gevent.spawn(download_img,"2.jpg","https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_match%2F0%2F6311385436%2F0.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1627992675&t=08d6f5ec50eb7570be0350512a67caea") ] )
  • 相关阅读:
    JavaScript table, grid, tree view or Gantt chart | TreeGrid
    Sign in
    DHtmlx Gantt
    Gantt Chart in JavaScript (HTML5) | FusionCharts
    无插件ExtJs4简单甘特图 / 蓝讯
    jsGantt(甘特图控件)
    FREE javascript gantt
    Python-Gantt
    JavaScript UI Library, Ajax Components & HTML5 Framework
    我的SPE甘特图
  • 原文地址:https://www.cnblogs.com/fengwenzhee/p/14969377.html
Copyright © 2011-2022 走看看