欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python学习 之 协程

程序员文章站 2024-02-09 12:23:10
协程的概念, gevent 模块...


理论知识点

  • 将线程切分为更小的单位, 称之为协程
  • 每个单位如果遇到 io, 程序内自动切换
  • 协程是应用程序级别, os 无感

gevent 模块

from gevent import monkey; monkey.patch_all()
import gevent
import time

def eat(name):
    print("%s eat 1" % name)
    time.sleep(3)
    print("%s eat 2" % name)


def play(name):
    print("%s play 1" % name)
    time.sleep(2)
    print("%s play 2" % name)


# 可以直接 join(), 用法和进程 线程相同
# ge = gevent.spawn(eat, "Tim")
# gp = gevent.spawn(play, "Tom")

# ge.join()
# gp.join()

# 也可以使用 joinall([]), 参数是一个列表
gevent.joinall([
    gevent.spawn(eat, "Tim"),
    gevent.spawn(play, "Tom")
])


greenlet 模块

""" - 比较简单粗暴, 声明切换过程 """
import greenlet 

def eat(name):
    print("%s eat 1" % name)
    # No. 2
    gp.switch("Tim")
    print("%s eat 2" % name)
    # No. 4
    gp.switch()

def play(name):
    print("%s play 1" % name)
    # No. 3
    ge.switch()
    print("%s play 2" % name)

# greenlet 对象
ge = greenlet.greenlet(eat)
gp = greenlet.greenlet(play)

# No. 1
# 第一次使用需要传参, 之后的使用不需要
ge.switch("Tim")


示例 - 使用协程单线程实现并发

  • server.py
    from gevent import monkey, spawn;monkey.patch_all()
    from socket import socket,AF_INET,SOCK_STREAM
    from threading import Thread,current_thread
    
    def communicat(conn):
        print("子线程: %s" % current_thread().getName())
        while True:
            try:
                data = conn.recv(1024)
                if not data:break
                conn.send(data.upper())
            except ConnectionRefusedError:
                break
        conn.close()
    
    
    def server(ip, port):
        print("主线程: %s" % current_thread().getName())
        s = socket(AF_INET, SOCK_STREAM)
        s.bind((ip, port))
        s.listen(5)
    
        while 1:
            conn, addr = s.accept()
            print(addr)
            # t = Thread(target=communicat, args=(conn,))
            # t.start()
            spawn(communicat, conn)
        s.close()
    
    if __name__ == "__main__":
        g = spawn(server, "127.0.0.1", 8081)
        g.join()
    
    
  • client.py
    from socket import socket,AF_INET,SOCK_STREAM
    from threading import Thread, current_thread
    
    def client():
        c = socket(AF_INET, SOCK_STREAM)
        c.connect(("127.0.0.1", 8081))
    
        while 1:
            msg = "%s say hello" % current_thread().getName()
            c.send(msg.encode("utf-8"))
            r = c.recv(1024)
            print(r.decode("utf-8"))
    
        c.close()
    
    
    if __name__ == "__main__":
        for i in range(500):
            t = Thread(target=client)
            t.start()
    
    

本文地址:https://blog.csdn.net/yang_kaiyue/article/details/107420119

相关标签: Python