您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

异步大作战:协程、await、asyncio 浅尝

时间:2023-08-25 14:22:59  来源:  作者:测试玩家勇哥

1. 什么是协程?

协程,也有人叫他微线程,是一种用户态内的上下文切换技术。简单说,就是一种能在单线程内实现多任务切换的技术,这种技术不是计算机提供的,是人为创造的。
比如:你一边蹲坑,一边玩手机,一边抽烟,同时进行多个任务!这就是协程的精髓。

2. 协程怎么用?

我们来看一下几种实现协程的方法。

2.1 使用 greenlet 库

这是一种早期的协程方案,不过用得比较少了。

from greenlet import greenlet

def func1():
    print(1) # 第二步
    gr2.switch() # 切换到func2
    print(2) # 第四步
	
def func2():
    print(3) # 第三步
    gr1.switch() # 切换到func1
    print(4) # 第五步

gr1 = greenlet(func1)
gr2 = greenlet(func2)

gr1.switch() # 第一步

2.2 使用 yield 关键字

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、4、2

2.3 使用 asyncio 库

Python/ target=_blank class=infotextkey>Python 3.4 及以后版本,可以使用 asyncio 库来实现协程。

import asyncio

async def func1():
    print(1)
    # 遇到三上老师的网络 IO 请求
    awAIt asyncio.sleep(2) # 模拟IO耗时操作,开始切换到其他任务
    print(2)

async def func2():
    print(3)
    # 又遇到苍老师的网络IO请求
    await asyncio.sleep(2) # 切换
    print(4)

tasks = [
    asyncio.ensure_future(func1()),
    asyncio.ensure_future(func2())
]

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

上述代码中要注意的地方:遇到 IO 阻塞,会自动切换。

2.4 使用 async 和 await 关键字

Python 3.5 及以后版本引入了 async 和 await 关键字,更加简洁方便。

import asyncio

async def func1():
    print(1)
  # 又找三上老师的网络 IO 请求
    await asyncio.sleep(2)
    print(2)

async def func2():
    print(3)
   # ...网络IO请求
    await asyncio.sleep(2)
    print(4)

tasks = [
    asyncio.ensure_future(func1()),
    asyncio.ensure_future(func2())
]

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

归纳总结上面的例子,他们的共同步骤都是:

  1. 定义协程函数:注意,协程函数的调用,获取到的是一个协程对象,而不是直接执行函数。

  2. 在协程函数中进行异步操作

  3. 创建事件循环(asyncio ):使用 asyncio 创建一个事件循环对象, asyncio.get_event_loop() 获取事件循环实例。

  4. 将协程函数添加到任务列表:将协程函数添加到任务列表中,等待事件循环调度执行。

  5. 运行事件循环

总结起来,这些代码段都是通过异步编程实现协程,使多个任务能够在非阻塞的情况下并发执行。无论是使用 greenletyieldasyncio 还是 async/await,它们都基于协程的概念,以不同的方式来实现异步任务的调度和执行

3. 实战小栗子:异步下载图片

首先,让我们用普通的同步方式来下载图片。

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 f:
        f.write(response.content)

url_list = [
    'https://api.dujin.org/bing/1920.php',
    'https://api.dujin.org/bing/1920.php',
    'https://api.dujin.org/bing/1920.php'
]

for item in url_list:
    download_image(item)

接下来,我们使用异步编程来同时下载多张图片。

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)
        print('下载完成', url)

async def main():
    async with aiohttp.ClientSession() as session:
        url_list = [
            'https://api.dujin.org/bing/1920.php',
            'https://api.dujin.org/bing/1920.php',
            'https://api.dujin.org/bing/1920.php'
        ]
        tasks = [asyncio.create_task(fetch(session, url)) for url in url_list]

        await asyncio.wait(tasks)

asyncio.run(main())

4. 异步小栗子:单接口自动化测试。

在接口自动化测试中,如果测试用例全部没有依赖关系,比如单接口测试中,所有参数独立定义好后,就可以考虑使用异步接口请求。这样相当于又小压了一波接口。

import aiohttp
import asyncio

async def test_api(endpoint):
    async with aiohttp.ClientSession() as session:
        async with session.get(endpoint) as response:
            result = await response.json()
            print(f"请求 {endpoint} 返回的结果:{result},断言.......")

async def main():
    # 接口测试用例可以用各种方式读取出来,这里简单搞一搞
    api_endpoints = [
        "http://api.example.com/endpoint1?name=1&age=1",
        "http://api.example.com/endpoint1?name=汉字&age=1",
        "http://api.example.com/endpoint1?name=**&age=1"
        ...
    ]
    tasks = [asyncio.create_task(test_api(endpoint)) for endpoint in api_endpoints]
    await asyncio.wait

asyncio.run(main())

这样就可以简单的实现异步请求的接口自动化测试啦。



Tags:异步   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C#异步编程:Task.Run vs. async-await,掌握基础与高级用法
概述:C#中的异步编程有两主要方式:Task.Run用于在后台线程执行同步操作,而async-await更适用于清晰表达异步流程。基础用法展示了它们的简单应用,高级用法则演示了它们的结合使...【详细内容】
2024-03-09  Search: 异步  点击:(23)  评论:(0)  加入收藏
有了这五个方法,轻松处理异步任务
本文我将介绍 Promise 对象上 5 个非常有用的方法,掌握这些方法之后,可以让你更好地解决工作遇到的一些异步问题。在 JavaScript 中,许多操作都是异步的,比如发起网络请求、读取...【详细内容】
2024-03-07  Search: 异步  点击:(26)  评论:(0)  加入收藏
异步Rust:构建实时消息代理服务器
在本文中,我们将深入研究使用Rust构建实时消息代理服务器,展示其强大的并发特性。我们将使用Warp作为web服务器,并使用Tokio来管理异步任务。此外,我们将创建一个WebSocket客户...【详细内容】
2024-02-01  Search: 异步  点击:(57)  评论:(0)  加入收藏
Java 异步编程本应更简单才对
在过去的好多年里,多线程和异步一直作为 Java 技术里的高级部分,在技术序列中,一个语言分为入门部分、进阶部分和高级部分,所以,异步是作为其中的高级技术部分存在的。关于异步和...【详细内容】
2023-12-12  Search: 异步  点击:(188)  评论:(0)  加入收藏
异步编程与CompletableFuture
在现代软件开发中,异步编程已经成为一种常见的编程范式。它能够提高程序的性能和响应速度,使得程序在执行I/O密集型操作时能够更加高效地利用系统资源。在异步编程中,一种常见...【详细内容】
2023-12-08  Search: 异步  点击:(121)  评论:(0)  加入收藏
聊聊阻塞IO 非阻塞IO 异步IO,你学会了吗?
Netty 的高性能架构,是基于一个网络编程设计模式 Reactor 进行设计的。现在,大多数与 I/O 相关的组件,都会使用 Reactor 模型,比如 Tomcat、Redis、Nginx 等,可见 Reactor 应用的...【详细内容】
2023-12-06  Search: 异步  点击:(154)  评论:(0)  加入收藏
深入浅出JavaScript异步编程
浏览器中的 JavaScript 是典型的事件驱动型程序,即它们会等待用户触发后才真正的执行,而基于的JavaScript的服务器通常要等待客户端通过网络发送请求,然后才能执行。这种异步编...【详细内容】
2023-12-04  Search: 异步  点击:(188)  评论:(0)  加入收藏
聊聊Python协程和异步编程
协程和异步编程是Python中处理并发和异步任务的重要概念。协程是一种轻量级的并发编程方式,它允许程序在执行过程中暂停和恢复,以便处理其他任务。异步编程模型则是基于协程的...【详细内容】
2023-11-29  Search: 异步  点击:(245)  评论:(0)  加入收藏
JavaScript中的异步处理你知道哪些方法?你用对了吗?
JavaScript中的异步处理是开发者在日常开发过程中必须面对的一个重要问题。由于JavaScript是单线程的,因此对于一些可能需要长时间执行的操作,如网络请求、IO操作等,如果采用同...【详细内容】
2023-11-29  Search: 异步  点击:(206)  评论:(0)  加入收藏
深入 .NET 异步编程:Task 与 ValueTask 的区别与选择
在 .NET 中,Task 和 ValueTask 都是用于表示异步操作的类型,但它们有一些重要的区别。TaskTask 是最常见的表示异步操作的类型。它通常用于表示耗时的、异步的操作,比如从文件...【详细内容】
2023-11-26  Search: 异步  点击:(189)  评论:(0)  加入收藏
▌简易百科推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(86)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(58)  评论:(0)  加入收藏
使用Python进行数据分析,需要哪些步骤?
Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单,代码可读性强,一段好的Python代码,阅读起来像是在读一篇外语文章。Python这种特...【详细内容】
2024-01-15  程序员不二    Tags:Python   点击:(162)  评论:(0)  加入收藏
Python语言的特点及应用场景, 同其它语言对比优势
Python语言作为一种高级编程语言,具有许多独特的特点和优势,这使得它在众多编程语言中脱颖而出。在本文中,我们将探讨Python语言的特点、应用场景以及与其他语言的对比优势。一...【详细内容】
2024-01-09    今日头条  Tags:Python语言   点击:(253)  评论:(0)  加入收藏
站内最新
站内热门
站内头条