python 高级-- 协程 + 协程案例_ 图片下载



协程:

    sinstance (对象 类型 )  判断是否是 只当类型

    ininstance ( [1,3,5] , Iterable )




自定义可迭代对象: ------类中使用    __ iter__ 方法




next 启动生成器

send 启动生成器 ( 第一次不能传参数 )



a = 函数( )

b = next ( a )

b = a.send (参数 )






自定义迭代器对象 :

        有 _iter__ 函数  

有迭代器 

        有 iter 函数   有 next 函数







协程 greenlet

a = greenlet.greenlet(函数名)

ea.switch ( )



b = greenlet . getcurrent  获取当前的协程对象











pip3 install gevent  -----> 安装第三方包'





gecent 协程

gevent . sleep (0.2) 必须用本 耗时操作

--->monkey. patch_all ( )

---:>from gevent import monkey  打补丁 ,识别耗时操作





a = gevent . spawnn ( 函数名)

print (a)

a.join() 主线程 等待 线程



------- gevent.getcurrent ( ) 查看当前线程





网络模块:

import urllib.request  



a = urllib.request.urlopen ( 变量)

读取网络资源数据:

      a.read ()





等待所有协程完成:

a .joinall ( a,b,c) 







正则表达式 模块:   re

变量. group ( )  ----> 获取数据












import greenlet
import time

def work1():
    # 获取当前的协程对象
    # result = greenlet.getcurrent()
    # print(result)
    for i in range(3):
        print("work1工作中...")
        time.sleep(0.2)
        # 切换到第二个协程执行对应的任务
        g2.switch()


def work2():
    # 获取当前的协程对象
    # result = greenlet.getcurrent()
    # print(result)
    for i in range(3):
        print("work2工作中...")
        time.sleep(0.2)
        # 切换到第一个协程执行对应的任务
        g1.switch()

# 创建协程1指定完成对应的任务a
g1 = greenlet.greenlet(work1)
# 创建协程2指定完成对应的任务
g2 = greenlet.greenlet(work2)

if __name__ == '__main__':

    print(g1, g2)
    # 切换到指定协程执行对应的任务
    g1.switch()

这里写图片描述

# gevent是一个第三方包,封装的是greenlet,会根据耗时操作自动进行协程之间的切换执行
import gevent
import time
from gevent import monkey
# 打补丁,识别耗时(time.sleep, 网络请求,tcp accept, tcp recv等)操作,完成协程之间的切换执行
monkey.patch_all()

# def show(*args):
#     print(args)
#
# my_tuple = (1, 45)
# show(*my_tuple)


def task1():
    # 查看当前线程
    print("task1:", gevent.getcurrent())
    for i in range(3):
        print("task1执行中...")
        time.sleep(0.2)# 默认不会认为系统的耗时操作是耗时的,不识别
        #gevent.sleep(0.2)


def task2():
    # 查看当前线程
    print("task2:", gevent.getcurrent())
    for i in range(3):
        print("task2执行中...")
        time.sleep(0.2)
        # gevent.sleep(0.2)

if __name__ == '__main__':
    # 创建协程1指定对应的任务
    g1 = gevent.spawn(task1)
    g2 = gevent.spawn(task2)
    # print(g1, g2)

    # 主线程等待协程执行完成以后程序再退出
    # g1.join()
    # g2.join()

    while True:
        # 循环等待接收客户端的连接请求
        time.sleep(0.2)

    # 注意点: 不需要加join的条件是, 1. 主线程需要一直运行好比是死循环, 2. 循环的代码里面必须有耗时操作

这里写图片描述

import gevent
import urllib.request  # 网络相关模块
from gevent import monkey

# 打补丁,识别网络请求的耗时操作,让多个协程自动进行切换执行
monkey.patch_all()


# 下载图片的函数
def download_img(img_url, img_name):
    print(gevent.getcurrent())

    try:
        # 根据图片地址打开网络资源--> 相当于打开网络中的某个文件
        response = urllib.request.urlopen(img_url)
        with open(img_name, "wb") as img_file:
            while True:
                # 读取网络资源数据
                img_data = response.read(1024)
                if img_data:
                    # 把数据写入到指定文件里面
                    img_file.write(img_data)
                else:
                    break
    except Exception as e:
        print("下载网络图片出现异常:", e)
    else:
        print("图片下载成功:", img_name)

if __name__ == '__main__':
    # 准备下载图片的地址
    img_url1 = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=812586171,724963760&fm=27&gp=0.jpg"
    img_url2 = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1293860636,1088191402&fm=27&gp=0.jpg"
    img_url3 = "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2011032701,3112503813&fm=27&gp=0.jpg"

    # 创建协程对象
    g1 = gevent.spawn(download_img, img_url1, "1.jpg")
    g2 = gevent.spawn(download_img, img_url2, "2.jpg")
    g3 = gevent.spawn(download_img, img_url3, "3.jpg")

    print(g1, g2, g3)

    # 主线程等待所有的协程执行完成以后程序再退出
    gevent.joinall([g1, g2, g3])

这里写图片描述

猜你喜欢

转载自blog.csdn.net/haohao143/article/details/82595013
今日推荐