Python 协程

协程基础

底层实现

  • 协程的底层是使用greenlet模块来实现的
from greenlet import greenlet

def func1():
    print("eat start")# 2
    g2.switch()
    print("eat end")# 4
    g2.switch()


def func2():
    print("play start")# 3
    g1.switch()
    print("play end")# 5


g1 = greenlet(func1)
g2 = greenlet(func2)
g1.switch()# 1

介绍

  • 当遇到IO操作时将程序切换到其他函数继续执行会提高CPU的利用效率
  • 一个线程可以开启500个协程
  • 更适用于网络操作中

安装

pip install gevent

应用

协程实现

from gevent import monkey;monkey.patch_all()
# 将下面导入的所有的包中的阻塞操作封装成gevent可以识别的阻塞
# 没有这行代码time.sleep语句是不被gevent识别的
# 使用gevent一定要将这一行代码放到开头
import time
import gevent

def func1():
    print("eat start")
    time.sleep(1)# 阻塞
    print("eat end")



def func2():
    print("play start")
    time.sleep(1)# 阻塞
    print("play end")

g1 = gevent.spawn(func1)# 创建协程
g2 = gevent.spawn(func2)
g1.join() # 等待协程g1结束
g2.join() # 等待协程g2结束
# gevent可以自动调度协程,实现在遇到IO操作时自动切换

协程爬虫

from gevent import monkey;monkey.patch_all()# 感知其他包中的阻塞
import requests
import gevent

def geturl(url):
    rep = requests.get(url)
    print(url,len(rep.text))


g1 = gevent.spawn(geturl,"https://www.baidu.com")# 创建协程
g2 = gevent.spawn(geturl,"https://www.iqiyi.com")
g3 = gevent.spawn(geturl,"https://www.taobao.com")
g4 = gevent.spawn(geturl,"https://www.sohu.com")

gevent.joinall([g1,g2,g3,g4])# 将全部协程join与主程序同步,接收的是可迭代对象
# 同步的原因:异步执行同步接收结果,如果不同步则主程序直接执行完毕接收不到结果

协程实现socket并发

server

from gevent import monkey;monkey.patch_all()
import socket
import gevent
def func(conn):

    conn.send(b"hello")
    print(conn.recv(1024).decode("utf8"))
    conn.close()
sk = socket.socket()
sk.bind(("127.0.0.1",8080))
sk.listen()
g_list = []
while True:
    conn, addr = sk.accept()
    g = gevent.spawn(func,conn)
    g_list.append(g)



sk.close()

client

import socket
sk = socket.socket()
sk.connect(("127.0.0.1",8080))
print(sk.recv(1024).decode("utf8"))
msg = input(">>>").encode("utf8")
sk.send(msg)
posted @ 2019-11-17 22:58  长江尾  阅读(119)  评论(0编辑  收藏  举报