Python学习 之 协程

本文深入探讨了使用Python的gevent和greenlet模块实现协程和单线程并发的技巧。通过具体示例,展示了如何利用协程提高IO密集型任务的效率,包括并发函数的定义、greenlet手动切换以及gevent在服务器端的应用。
摘要由CSDN通过智能技术生成


gevent 模块

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


# 定义使用协程执行的两个函数
# 间隔随机时间, 打印下一个(模拟 io)
# 因为 io 阻塞时间不同, 所以输出结果也不同
def myprint1(i):
    print(i)
    time.sleep(random.randint(1,3))
    print(i+1)
    time.sleep(random.randint(1,3))
    print(i+2)


def myprint2():
    print("x")
    time.sleep(random.randint(1,3))
    print("y")
    time.sleep(random.randint(1,3))
    print("z")
    

if __name__ == "__main__":
    gevent.joinall([
    	# 参数依次写在 spawn 后边即可
        gevent.spawn(myprint1, 10),
        gevent.spawn(myprint2),
    ])

    # 等同于
    # g1 = gevent.spawn(myprint1, 10)
    # g2 = gevent.spawn(myprint2)

    # g1.join()
    # g2.join()


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()
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值