python基础:协程

目录

一、yield的简单实现

二、greenlet 模块

三、gevent模块


 


协程:协助程序,线程和进程都是抢占式特点,线程和进程的切换我们是不能参与的。而协程是非抢占式特点,协程也存在着切换,这种切换是由我们用户来控制的。协程主解决的是IO的操作。

协程,又称微线程,纤程。英文名Coroutine。

优点1: 协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

优点2: 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能

一、yield的简单实现

import time

def test1():
    while True:
        print('test1......')
        time.sleep(0.1)
        yield

def test2():
    while True:
        print('test2......')
        time.sleep(0.1)
        yield

def main():
    g1=test1()
    g2=test2()
    while True:
        next(g1)
        next(g2)

if __name__ == '__main__':
    main()

运行结果:

test1......
test2......
test1......
test2......
......

 

二、greenlet 模块

greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator

安装 :pip3 install greenlet。如果引入的时候还是报错,使用pycharm进行下载安装,

选择 file --> settings --> Project:项目名称 --> Project Interpreter-->…

greenlet模块

- gr1=greenlet(目标函数)

- gr1.switch() 切换执行

创建简单的协程程序

import greenlet,time

def test1():
    for i in range(3):
        print('test1...',i)
        time.sleep(0.5)
        g2.switch()

def test2():
    for i in range(3):
        print("test2...",i)
        time.sleep(0.5)
        g1.switch()


if __name__ == '__main__':
    g1=greenlet.greenlet(test1) # 指定g1执行的目标
    g2=greenlet.greenlet(test2)

    g1.switch()  # 让程序去g1指定的目标去执行
    print('程序结束了...')

运行结果·:

test1... 0
test2... 0
test1... 1
test2... 1
test1... 2
test2... 2
程序结束了...

 

三、gevent模块

 

import gevent,time
from gevent import monkey

# 打补丁
monkey.patch_all()

# 如果程序中没有耗时操作就顺序执行
def test1():
    for i in range(3):
        print('test1....',i)
        time.sleep(0.5)   # 注意事项:需要使用gevent.sleep()耗时操作才能自动切换

def test2():
    for i in range(3):
        print('test2....',i)
        time.sleep(0.5)


if __name__ == '__main__':
    g1=gevent.spawn(test1)  # 指定执行目标
    g2=gevent.spawn(test2)
    # 等待g1,g2指定的目标执行完后程序才往下执行
    g1.join()
    g2.join()
    print('程序结束了....')

运行结果:

test1.... 0
test2.... 0
test1.... 1
test2.... 1
test1.... 2
test2.... 2
程序结束了....

gevent.joinall()方法

import gevent,time
from gevent import monkey

# 打补丁
monkey.patch_all()

# 如果程序中没有耗时操作就顺序执行
def test1():
    for i in range(2):
        print('test1....',i)
        time.sleep(0.5)

def test2():
    for i in range(2):
        print('test2....',i)
        time.sleep(0.5)


if __name__ == '__main__':
    # 简化写法,当joinall中的内容全部执行完后程序继续往下执行
    gevent.joinall([
        gevent.spawn(test1),  # 指定执行目标
        gevent.spawn(test2)
        # 等待g1,g2指定的目标执行完后程序才往下执行
    ])
    print('程序结束了....')

运行结果;

test1.... 0
test2.... 0
test1.... 1
test2.... 1
程序结束了....

练习:编写程序实现图片的拷贝

首先引进requests模块

首先点击 file-->setting-->project.day22-多任务(文件所在根目录)---->project Interpreter

找到requests模块,然后下载

应用该模块

 

开始编写程序:

# 初始requests模块
import requests,gevent
# 给图片具体地址赋值变量
ur1= 'https://b-ssl.duitang.com/uploads/item/201612/10/20161210005234_hZzLn.jpeg'
# 获取该图片地址
response=requests.get(ur1)
# response.content  # 获取图片的二进制数据
# 将该图片以二进制形式写进一个新的图片文件
with open('img/1.jpeg',mode='wb') as f:
    f.write(response.content)

运行结果:

 

使用gevent模块同时拷贝两张图片

import requests,gevent
def download_img(url,img_name):
    
    response=requests.get(url)
    with open('img/'+img_name,mode='wb') as f:
        f.write(response.content)


if __name__ == '__main__':
    url= 'https://b-ssl.duitang.com/uploads/item/201612/10/20161210005234_hZzLn.jpeg'
    url1='http://img.netbian.com/file/2017/0427/ae20084a88ce11e47eb267acc53f86e5.jpg'
    # download_img(url,'mao.jpeg')
    # download_img(url1,'yanlingji.jpeg')
    gevent.joinall([
        gevent.spawn(download_img,url,'mao.jpeg'),
        gevent.spawn(download_img,url1,'yanlingji.jpeg')

    ])

运行结果:

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值