设为首页 加入收藏

TOP

Asyncio 协程异步笔记(一)
2023-09-23 15:43:39 】 浏览:167
Tags:Asyncio 程异步

协程 & asyncio & 异步

1. 协程 (coroutine)

协程不是计算机提供,而是程序员人为创造。

协程(coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块互相切换运行。例如:

def func1():
    print(1)
    ...
    print(2)
    
def func2():
    print(3)
    ...
    print(4)
    
func1()
func2()


实现协程有这么几种方法:

  • greenlet,早期模块。
  • yield 关键字。
  • asyncio 装饰器(python 3.4)
  • asyncawait 关键字(python 3.5)


1.1 greenlet 实现协程

pip3 install greenlet
from greenlet import greenlet

def func1():
    print(1)  # 第 2 步:输出 1
    gr2.switch()  # 第 3 步:切换到 func2 函数
    print(2)  # 第 6 步:输出 2
    gr2.switch()  # 第 7 步 切换到 func2 函数,从上一次执行的位置继续向后执行
    
def func2():
    print(3)  # 第 4 步:输出 3
    gr1.switch()  # 第 5 步:切换到 func1 函数,从上一次执行的位置继续向后执行
    print(4)  # 第 8 步:输出 4
    
gr1 = greenlet(func1)
gr2 = greenlet(func2)
gr1.switch()  # 第 1 步:去执行 func1 函数


1.2 yield 关键字

def func1():
    yield 1
    yield from func2()
    yield 2
    
def func2():
    yield 3
    yield 4
    
f1 = func1()
for item in f1:
    print(item)

伪实现,仅能实现协程的功能。



1.3 asyncio

在 python 3.4 及之后的版本。

import asyncio

@asyncio.coroutine
def func1():
    print(1)
    yield from asyncio.sleep(2)  # 遇到 IO 耗时操作,自动化切换到 tasks 中其它任务
    print(2)
    
@asyncio.coroutine
def func2():
    print(3)
    yield from asyncio.sleep(2)  # 遇到 IO 耗时操作,自动化切换到 tasks 中其它任务
    print(4)
    
tasks = [
    asyncio.ensure_future(func1())
    asyncio.ensure_future(func2())
]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

注意:遇到 IO 阻塞自动切换。



1.4 aynsc & await 关键字

在 python 3.5 及之后的版本。

import asyncio

async def func1():
    print(1)
    # 网络 IO 请求:下载一张图片
    await asyncio.sleep(2)  # 遇到 IO 耗时操作,自动化切换到 tasks 中的其它任务。
    print(2)
    
async def func2():
    print(3)
        # 网络 IO 请求:下载一张图片
    await asyncio.sleep(2)  # 遇到 IO 耗时操作,自动化切换到 tasks 中的其它任务。
    print(4)
    
tasks = [
    asyncio.ensure_future(func1())
    asyncio.ensure_future(func2())
]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))    


2. 协程的意义

在一个线程中如果遇到 IO 等待时间,线程不会傻等,而是利用空闲时间再去干点其它事情。



案例:下载三张图片(网络 IO):

  • 普通方式(同步)

    pip3 install requests
    
    import requests
    
    def download_image(url):
        print("开始下载:", url)
        response = requests.get(url)
        print("下载完成")
    
        file_name = url.rsplit("_")[-1]
        with open(file_name, mode="wb") as file_object:
            file_object.write(response.content)
    
    url_list = [ "https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg",
                "https://www3.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar__ChcCSV2BBICAUntfAADjJFd6800429.jpg",
                "https://www3.autoimg.cn/newsdfs/g26/M0B/3C/65/120x90_0_autohomecar__ChcCP12BFCmAIO83AAGq7vk0sGY913.jpg", 
    ]
    
    for item in url_list:
        download_image(item)
    


  • 协程方式(异步)

    pip3 install aiohttp
    
    import aiohttp
    import asyncio
    
    async def fetch(session, url):
        print("发送请求:", url)
        async with session.get(url, verify_ssl=False) as response:
            content = await response.content.read()
            file_name = url.rsplit("_")[-1]
            with open(file_name, mode="wb") as file_object:
                file_object.write(content)
                
    async def main():
        async with aiohttp.ClientSession() as session:
            url_list = [ "https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg",
                "https://www3.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar__ChcCSV2BBICAUntfAADjJFd6800429.jpg",
                &qu
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python变量:创建、类型、命名规.. 下一篇【matplotlib基础】--几何图形

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目