python进阶--协程

协程简述

  • 定义:协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序”。
  • 从技术角度讲,协程就是一个你可以暂停执行的函数,或者干脆把协程理解成生成器
  • 本质是单任务,依赖于线程,占用资源少
  • 实现方式:yield、 greenlet模块、gevent模块
  • yield能实现协程
  • greenlet:可以实现协程,不过每一次都要人为的去指向下一个该执行的协程,显得太过麻烦。
  • gevent:遇到需要耗时等待的io操作时,能够自动切换任务跳到下一个协程继续执行

yield

  • python3.4引入协程,用yield实现。3.5引入协程语法
  • 利用yield实现多任务–协程
def demo1():
    for i in range(3):
        print('正在运行demo1---{}'.format(i))
        yield

def demo2():
    for i in range(3):
        print('正在运行demo2---{}'.format(i))
        yield      

g1 = demo1()
g2 = demo2()

print(g1)

while True:
    try:
        next(g1)
        next(g2)
    except StopIteration:
        break

>
正在运行demo1---0
正在运行demo2---0
正在运行demo1---1
正在运行demo2---1
正在运行demo1---2
正在运行demo2---2
  • yield实现协程,并与主进程进行数据共享
def simple_coroutine():
    print('转到协程')
    x = yield ## 返回到主进程
    print('协程接收到主进程值x:{0}'.format(x))

sc = simple_coroutine()
print('开始主进程')

# 可以使用sc.send(None),效果一样
next(sc)  ## 预激

print('yield--回到主进程')
sc.send('zhexiao') # send调用

>开始主进程
 转到协程
 yield--回到主进程
 协程接收到主进程值x:zhexiao
 StopIteration

greenlet模块

  • 需要指定switch(),比较麻烦
from greenlet import greenlet
import time
def test1():
    while True:
        print('---A----')
        gr2.switch()
        time.sleep(0.5)
def test2():
    while True:
        print('----B----')
        gr1.switch()
        time.sleep(0.5)
"""
greenlet这个类对yield进行的封装
"""
gr1= greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

gevent模块

  • 语法
  • gevent.spawn() :开启协程,第一个参数为要执行的任务
  • join():gevent中线程默认不会等待协程执行,需要使用该方法
  • 协程切换:
    - gevent.sleep(0)创建了一个阻塞,gevent在运行到这里时就会自动切换函数切换函数
    - monkey.patch_all()#使用此方法,会将代码中检查一遍,如有time等延时方法,会自动转换为gevent.sleep()
  • gevent.sleep()方法

import gevent
def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)
def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)
def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        #gevent.sleep(0.5)
g1 = gevent.spawn(f1,5)
g2 = gevent.spawn(f2,5)
g3 = gevent.spawn(f3,5)
g1.join()
g2.join()
g3.join()

>
<Greenlet at 0x1068e54a8: f1(5)> 0
<Greenlet at 0x1068e55c0: f2(5)> 0
<Greenlet at 0x1068e56d8: f3(5)> 0
<Greenlet at 0x1068e56d8: f3(5)> 1
<Greenlet at 0x1068e56d8: f3(5)> 2
<Greenlet at 0x1068e56d8: f3(5)> 3
<Greenlet at 0x1068e56d8: f3(5)> 4
<Greenlet at 0x1068e54a8: f1(5)> 1
<Greenlet at 0x1068e55c0: f2(5)> 1
<Greenlet at 0x1068e54a8: f1(5)> 2
<Greenlet at 0x1068e55c0: f2(5)> 2
<Greenlet at 0x1068e54a8: f1(5)> 3
<Greenlet at 0x1068e55c0: f2(5)> 3
<Greenlet at 0x1068e54a8: f1(5)> 4
<Greenlet at 0x1068e55c0: f2(5)> 4
  • monkey.patch_all() 补丁
import gevent
import time
from gevent import monkey

monkey.patch_all()

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

g1 = gevent.spawn(f1,5)
g2 = gevent.spawn(f2,5)

g1.join()
g2.join()

>
<Greenlet at 0x1050ebb38: f1(5)> 0
<Greenlet at 0x1050ebe80: f2(5)> 0
<Greenlet at 0x1050ebb38: f1(5)> 1
<Greenlet at 0x1050ebe80: f2(5)> 1
<Greenlet at 0x1050ebb38: f1(5)> 2
<Greenlet at 0x1050ebe80: f2(5)> 2
<Greenlet at 0x1050ebb38: f1(5)> 3
<Greenlet at 0x1050ebe80: f2(5)> 3
<Greenlet at 0x1050ebb38: f1(5)> 4
<Greenlet at 0x1050ebe80: f2(5)> 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值