zoukankan      html  css  js  c++  java
  • 协程—gevent模块的使用

    gevent:认识一

    import time
    import gevent
    
    # 带有io操作的内容写在函数里,然后提交func函数给gevent
    def func():
        print("start func ...")
        gevent.sleep(1)
        print("end func ...")
    
    g1 = gevent.spawn(func)
    
    time.sleep(1.5)
    

    1、程序执行到 g1 = gevent.spawn(func) 这一步之后,并不会执行func协程函数。如果后面没有了,程序会直接退出。

    2、所以需要加个阻塞(io阻塞或其他阻塞),让程序不能退出,那么程序遇到阻塞就会切换到func协程函数里面执行。那么事实到底是不是呢?

    3、这里我是用time.sleep(1.5)阻塞程序的,但是time,sleep(1.5)此时无效,程序等待1.5秒后退出,仍然没有执行func协程函数。尴尬喽!因为不认识time为阻塞函数,所以就不会切换到协程函数。那么怎么认识time.sleep()函数呢?就需要导入from gevent import monkey这个啦!

    4、协程就是在单线程中,多个任务不停地切换执行。如果线程不阻塞,程序很快运行结束了,那么协程就不会执行的。即使阻塞,也需要让协程认识才行,这样才会自动切换到协程函数里面执行。协程认识的阻塞函数就那么几个,可以查看monkey.patch_all(),主要就是socket的一些阻塞函数。

    gevent:认识二

    from gevent import monkey
    monkey.patch_all()
    import time         # 在time之前导入monkey,就认识time阻塞喽!
    import gevent
    
    # 带有io操作的内容写在函数里,然后提交func函数给gevent
    def func():
        print("start func ...")
        gevent.sleep(1)
        print("end func ...")
      
    g1 = gevent.spawn(func)
      
    time.sleep(1.5)

    一、gevent 如何检测是否能规避某个模块的io操作呢?在patch_all之前打印一次,在patch_all之后打印一次,如果两次的结果不一样,那么就说明能够规避io操作。

    二、不容易呀,终于执行协程函数了!但是用time.sleep()函数阻塞不好,因为不清楚协程函数到底需要执行多长时间呢?这里有另一个方法,见下面:

    gevent:认识三

    from gevent import monkey
    monkey.patch_all()   # 这两行是为了改变模块一些特性,如time模块,socket模块,这样才能识别time.sleep()与sock.accept()与sock.recv()等为阻塞函数,进行切换。
    import time
    import gevent
    
    def foo(a):
        print("Running in foo", a)
        gevent.sleep(2)
        print("switch to foo again")
    
    def func():
        print("Running in func ...")
        gevent.sleep(3)
        print("switch to func again...")
      
    # 将事件函数加入协程,就变成协程函数了
    g1 = gevent.spawn(func)
    g2 = gevent.spawn(foo, 1)
      
    # g1.join()
    # g2.join()
    gevent.joinall([g1, g2])   # 回收协程,比一个一个回收方便一点 

    gevent:协程解决网络阻塞实例,实现并发

    服务端:

    from gevent import monkey
    monkey.patch_all()
    import socket
    import gevent
    
    def func(conn):
        while True:
            msg = conn.recv(1024).decode("utf-8")
            MSG = msg.upper()
            conn.send(MSG.encode("utf-8"))
    
    server = socket.socket()           
    server.bind(("127.0.0.1", 3120))
    server.listen()
     
    while True:
        conn, addr = server.accept()
        gevent.spawn(func, conn)

    客户端:

    import time
    import socket
    from threading import Thread
    
    def client():
        client = socket.socket()        
        client.connect(("127.0.0.1", 3120))
    	
        while True:
            client.send(b"hello")
            data = client.recv(1024)
            print(data.decode())
            time.sleep(1)
            
    for i in range(5):
        Thread(target=client).start()
    

      

  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/liuhaidon/p/12434972.html
Copyright © 2011-2022 走看看