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

简介: 嘿,帅气的小伙!今天,咱们简单聊聊那些看似高级却又神秘莫测的异步编程技巧,俗称“协程”和“async/await

嘿,帅气的小伙!今天,咱们简单聊聊那些看似高级却又神秘莫测的异步编程技巧,俗称“协程”和“async/await”

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 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 使用 asyncawait 关键字

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

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())

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

总结

以上就是勇哥今天为各位小伙伴准备的内容,如果你想了解更多关于Python自动化测试的知识和技巧,欢迎关注我:公众号\博客\CSDN\B站:测试玩家勇哥;我会不定期地分享更多的精彩内容。感谢你的阅读和支持!


题外话,勇哥打算把新建的技术交流群,打造成一个活跃的高质量技术群。工作中遇到的技术问题,都可以在里面咨询大家,还有工作内推的机会。有兴趣的小伙伴,欢迎加我(记得备注是进群还是报名学习)


勇哥,10年落魄测试老司机,技术栈偏python,工作之余为粉丝进行简历修改、面试辅导、模拟面试、资料分享、一对一自动化测试教学辅导等副业发展。目前已服务十多位小伙伴,取得高薪offer。

关注公众号,测试干货及时送达

往期精选文章:
接口自动化测试项目2.0,让你像Postman一样编写测试用例,支持多环境切换、多业务依赖、数据库断言等
揭秘抓包利器:Python和Mitmproxy让您轻松实现接口请求抓取与分析!
构建高效的接口自动化测试框架思路
Pytest 快速入门
接口自动化之测试数据动态生成并替换
requests模块该如何封装?
接口自动化如何封装mysql操作
一文看懂python如何执行cmd命令
最通俗易懂python操作数据库
python-Threading多线程之线程锁
python正则一篇搞掂
性能测试之必备知识

性能分析思

Python + ChatGPT来实现一个智能对话的钉钉机器人
一文看懂python如何执行cmd命令
相关文章
|
9天前
|
开发者 Kotlin
揭秘Kotlin协程:如何在异步风暴中稳握错误处理之舵?
【9月更文挑战第12天】本文深入探讨了Kotlin协程框架下的错误处理机制,通过实例分析展示了如何利用`CoroutineExceptionHandler`进行结构化异常处理。文章详细介绍了全局与局部异常处理器的使用方法,并展示了如何在挂起函数中使用`try`表达式优雅地处理异常,以提高程序的健壮性和可维护性。
25 4
|
2天前
|
开发者 Python
探索Python中的异步编程:理解Asyncio和协程
【9月更文挑战第18天】在Python的世界中,异步编程是一个强大而神秘的概念。它像是一把双刃剑,掌握得好可以大幅提升程序的效率和性能;使用不当则可能让代码变得难以维护和理解。本文将带你一探究竟,通过深入浅出的方式介绍Python中asyncio库和协程的基本概念、使用方法及其背后的原理,让你对异步编程有一个全新的认识。
|
2月前
|
数据库 开发者 Python
实战指南:用Python协程与异步函数优化高性能Web应用
【7月更文挑战第15天】Python的协程与异步函数优化Web性能,通过非阻塞I/O提升并发处理能力。使用aiohttp库构建异步服务器,示例代码展示如何处理GET请求。异步处理减少资源消耗,提高响应速度和吞吐量,适用于高并发场景。掌握这项技术对提升Web应用性能至关重要。
71 10
|
2月前
|
数据处理 Python
深入探索:Python中的并发编程新纪元——协程与异步函数解析
【7月更文挑战第15天】Python 3.5+引入的协程和异步函数革新了并发编程。协程,轻量级线程,由程序控制切换,降低开销。异步函数是协程的高级形式,允许等待异步操作。通过`asyncio`库,如示例所示,能并发执行任务,提高I/O密集型任务效率,实现并发而非并行,优化CPU利用率。理解和掌握这些工具对于构建高效网络应用至关重要。
41 6
|
2月前
|
大数据 数据处理 API
性能飞跃:Python协程与异步函数在数据处理中的高效应用
【7月更文挑战第15天】在大数据时代,Python的协程和异步函数解决了同步编程的性能瓶颈问题。同步编程在处理I/O密集型任务时效率低下,而Python的`asyncio`库支持的异步编程利用协程实现并发,通过`async def`和`await`避免了不必要的等待,提升了CPU利用率。例如,从多个API获取数据,异步方式使用`aiohttp`并发请求,显著提高了效率。掌握异步编程对于高效处理大规模数据至关重要。
40 4
|
2月前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
【7月更文挑战第15天】Python异步编程借助协程和async/await提升并发性能,减少资源消耗。协程(async def)轻量级、用户态,便于控制。事件循环,如`asyncio.get_event_loop()`,调度任务执行。异步函数内的await关键词用于协程间切换。回调和Future对象简化异步结果处理。理解这些概念能写出高效、易维护的异步代码。
43 2
|
2月前
|
Python
从零到一:构建Python异步编程思维,掌握协程与异步函数
【7月更文挑战第15天】Python异步编程提升效率,通过协程与异步函数实现并发。从async def定义异步函数,如`say_hello()`,使用`await`等待异步操作。`asyncio.run()`驱动事件循环。并发执行任务,如`asyncio.gather()`同时处理`fetch_data()`任务,降低总体耗时。入门异步编程,解锁高效代码。
50 1
|
1月前
|
大数据 API 调度
Python中的异步编程:理解asyncio模块与协程
在现代编程中,异步编程越来越重要,特别是在处理大规模并发任务时。Python的asyncio模块提供了强大的工具来实现异步操作,其中协程是其核心机制之一。本文将深入探讨asyncio模块的基本概念、如何编写和管理异步任务,以及协程的工作原理和实际应用。
|
2月前
|
数据库 Python
我们来看一个简单的Python协程示例,它使用了`async`和`await`关键字。
我们来看一个简单的Python协程示例,它使用了`async`和`await`关键字。
|
2月前
|
存储 调度 Python
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。