python多任务实现方法之协程

多任务

多任务的实现方式,使用下面方法中的一个或者若干个进行组合:
1、多进程
2、多线程
3、协程
三种方式的实现和资源占用各有不同,其中资源占用和实现所需的系统开销(内存、cpu等)逐渐减少,实现难度依次降低。
可以简单的认为:一个进程可以包含多个线程,一个线程包含多个协程。

多任务实现方式的选择
cpu密集型任务:使用多进程
io密集型:使用多线程或协程

同步与异步:
同步:代码按照顺序执行,即前面一行代码执行完成才执行下一行代码,否则需要等待(阻塞)。

异步:后面代码无需等待(非阻塞)前面代码执行完即可执行。

并发:简单地理解为cpu数量小于进程数。
并行:简单地理解为cpu数量大于或等于进程数。

协程

协程的发展:python2时期的生成器(yield、yiled from)函数,到了python3进一步封装为async、await关键字实现的方法。
包含yield关键字的函数即为生成器函数。
生成器的调用:使用for循环或者next(生成器);
与生成器的数据交互:使用生成器的send方法;
关闭生成器:close方法。
生成器执行过程

def mtd():
    a = 1
    x = 2
    while True:
        x = yield a
        a += 1
        if a > 10:
            break
        print(x)


y = mtd()
next(y)
y.send(2)

执行顺序:

next --> 返回 a值1 --> send 2 --> x = 2 --> print 2

yield from 返回生成器对象(或者生成器函数的返回(return)值)
基本用法:

lis = [1, 2, 3]

def generator_2(lis):
    yield from lis

z=generator_2(lis)
type(z) # <generator object generator_2 at 0x0000016D1953D5E8>

复杂用法:

# 子生成器
def generator_1():
    total = 0
    while True:
        x = yield
        print('加', x)
        if not x:       # if not None: True
            break
        total += x
    return total


# 委托生成器
def generator_2():
    while True:
        # 建立调用方和子生成器的通道
        total = yield from generator_1()  # 子生成器
        print('加和总数是:', total)


# 调用方
def main():
    g2 = generator_2()
    g2.send(None)
    g2.send(2)
    g2.send(3)
    g2.send(None)


if __name__ == '__main__':
    main()

第三方模块
由于是第三方模块,需要安装

pip install greenlet
pip install gevent

gevent

import gevent
from gevent import monkey
monkey.patch_all() # 为下面的requests模块打补丁,进行重写和封装
import requests

def download(url):
    print("get: %s" % url)
    res = requests.get(url)
    data = res.text
    print(len(data), url)

# 多任务
g1 = gevent.spawn(download, 'https://www.a.com/') # 创建协程
g2 = gevent.spawn(download, 'https://www.b.com/')
g3 = gevent.spawn(download, 'https://www.c.com/')
g1.join()#等待协程结束
g2.join()
g3.join()

# 另一种实现方法
#gevent.joinall([
    gevent.spawn(download, 'https://www.a.com/'),
    gevent.spawn(download, 'https://www.b.com/'),
    gevent.spawn(download, 'https://www.c.com/')
])

greenlet

from greenlet import greenlet
import time

# 协程利用程序的IO 来切换任务
def demo1():
    while True:
        print("demo1")
        gr2.switch()
        time.sleep(0.5)


def demo2():
    while True:
        print("demo2")
        gr1.switch()
        time.sleep(0.5)


gr1 = greenlet(demo1)
gr2 = greenlet(demo2)

gr1.switch() # 启用协程

序列合并:

from itertools import chain

lis = [1, 2, 3]
dic = {
    "name": "juran",
    "age": 18
}

print(list(chain(lis, dic, range(5, 10))))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值