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