Python开发从入门到精通:异步编程与协程

《Python开发从入门到精通》设计指南第二十一篇:异步编程与协程

一、学习目标与重点

💡 学习目标 :掌握Python异步编程的基本概念和方法,包括协程、任务调度、事件循环等;学习asyncio、aiohttp等核心库的使用;通过实战案例开发异步应用程序。

⚠️ 学习重点:协程的定义与使用、任务调度、事件循环、asyncio库、aiohttp库、异步编程实战。

21.1 异步编程概述

21.1.1 什么是异步编程

异步编程是一种并发编程方式,通过非阻塞的操作提高程序的执行效率。在异步编程中,程序可以在等待I/O操作完成时继续执行其他任务,而不需要阻塞等待。

21.1.2 异步编程的优势

  • 提高执行效率:在等待I/O操作完成时,程序可以继续执行其他任务。
  • 降低资源消耗:减少了线程切换的开销。
  • 简化代码结构:通过协程和任务调度,代码结构更加简洁。

21.1.3 异步编程的应用场景

  • 网络通信:如HTTP请求、Web服务器、WebSocket通信等。
  • 文件操作:如大文件的读取和写入。
  • 数据库操作:如异步数据库查询。

21.2 协程的定义与使用

21.2.1 协程的定义

协程(Coroutine)是一种轻量级的线程,可以在程序中进行暂停和恢复。在Python中,协程可以通过async def关键字定义。

21.2.2 协程的使用

python 复制代码
import asyncio

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 运行协程
asyncio.run(hello())

21.2.3 协程的暂停与恢复

python 复制代码
import asyncio

# 定义协程
async def count():
    print('Counting...')
    await asyncio.sleep(1)
    print('Counted!')

# 运行多个协程
async def main():
    await asyncio.gather(count(), count(), count())

asyncio.run(main())

21.3 任务调度

21.3.1 创建任务

python 复制代码
import asyncio

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 创建任务
async def main():
    task1 = asyncio.create_task(hello())
    task2 = asyncio.create_task(hello())
    await task1
    await task2

asyncio.run(main())

21.3.2 任务的取消

python 复制代码
import asyncio

# 定义协程
async def hello():
    try:
        print('Hello, World!')
        await asyncio.sleep(1)
        print('Hello again!')
    except asyncio.CancelledError:
        print('Task cancelled!')

# 创建任务并取消
async def main():
    task = asyncio.create_task(hello())
    await asyncio.sleep(0.5)
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print('Main: Task cancelled!')

asyncio.run(main())

21.3.3 任务的超时

python 复制代码
import asyncio

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(2)
    print('Hello again!')

# 任务超时
async def main():
    try:
        await asyncio.wait_for(hello(), timeout=1)
    except asyncio.TimeoutError:
        print('Task timed out!')

asyncio.run(main())

21.4 事件循环

21.4.1 事件循环的概述

事件循环是异步编程的核心组件,负责调度任务的执行。事件循环会不断地从任务队列中取出任务并执行,直到任务队列为空。

21.4.2 获取事件循环

python 复制代码
import asyncio

# 获取事件循环
loop = asyncio.get_event_loop()

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 运行协程
loop.run_until_complete(hello())

21.4.3 事件循环的运行

python 复制代码
import asyncio

# 获取事件循环
loop = asyncio.get_event_loop()

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 运行多个协程
loop.run_until_complete(asyncio.gather(hello(), hello(), hello()))

21.5 asyncio库

21.5.1 asyncio的基本用法

python 复制代码
import asyncio

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 运行协程
asyncio.run(hello())

21.5.2 asyncio的常用函数

  • asyncio.run():运行协程。
  • asyncio.create_task():创建任务。
  • asyncio.gather():收集多个协程的结果。
  • asyncio.wait_for():等待协程完成,设置超时。
  • asyncio.sleep():暂停协程。

21.5.3 asyncio的高级用法

python 复制代码
import asyncio

# 定义协程
async def hello():
    print('Hello, World!')
    await asyncio.sleep(1)
    print('Hello again!')

# 使用Future对象
async def main():
    future = asyncio.Future()
    task = asyncio.create_task(hello())
    task.add_done_callback(lambda t: future.set_result(t.result()))
    await future

asyncio.run(main())

21.6 aiohttp库

21.6.1 安装aiohttp

bash 复制代码
pip install aiohttp

21.6.2 发送HTTP请求

python 复制代码
import aiohttp
import asyncio

# 发送GET请求
async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'https://www.example.com')
        print(html)

asyncio.run(main())

21.6.3 发送POST请求

python 复制代码
import aiohttp
import asyncio
import json

# 发送POST请求
async def post_data(session, url, data):
    async with session.post(url, data=data) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        data = {'name': '张三', 'age': 25}
        response = await post_data(session, 'https://httpbin.org/post', data)
        print(response)

asyncio.run(main())

21.6.4 发送JSON请求

python 复制代码
import aiohttp
import asyncio
import json

# 发送JSON请求
async def post_json(session, url, data):
    async with session.post(url, json=data) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        data = {'name': '张三', 'age': 25}
        response = await post_json(session, 'https://httpbin.org/post', data)
        print(response)

asyncio.run(main())

21.7 实战案例:异步HTTP客户端

21.7.1 需求分析

开发一个异步HTTP客户端,支持以下功能:

  • 发送HTTP请求。
  • 并发发送多个HTTP请求。
  • 处理响应数据。

21.7.2 代码实现

python 复制代码
import aiohttp
import asyncio
import time

# 发送HTTP请求
async def fetch(session, url):
    start_time = time.time()
    async with session.get(url) as response:
        text = await response.text()
        elapsed_time = time.time() - start_time
        return url, len(text), elapsed_time

# 并发发送HTTP请求
async def main():
    urls = [
        'https://www.example.com',
        'https://www.google.com',
        'https://www.github.com',
        'https://www.python.org',
        'https://www.djangoproject.com'
    ]
    
    async with aiohttp.ClientSession() as session:
        tasks = [asyncio.create_task(fetch(session, url)) for url in urls]
        results = await asyncio.gather(*tasks)
        
        for url, length, elapsed_time in results:
            print(f'URL: {url}, 响应长度: {length}, 耗时: {elapsed_time:.2f}秒')

# 运行程序
if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main())
    elapsed_time = time.time() - start_time
    print(f'总耗时: {elapsed_time:.2f}秒')

21.7.3 实施过程

  1. 安装aiohttp库。
  2. 定义发送HTTP请求的协程函数。
  3. 定义并发发送HTTP请求的协程函数。
  4. 运行程序。

21.7.4 最终效果

通过异步HTTP客户端,我们可以实现以下功能:

  • 发送HTTP请求。
  • 并发发送多个HTTP请求。
  • 处理响应数据。

21.8 实战案例:异步Web服务器

21.8.1 需求分析

开发一个异步Web服务器,支持以下功能:

  • 处理HTTP请求。
  • 提供静态文件服务。
  • 实现简单的API接口。

21.8.2 代码实现

python 复制代码
from aiohttp import web
import asyncio

# 处理根路径请求
async def handle_root(request):
    return web.Response(text='Hello, World!')

# 处理API接口请求
async def handle_api(request):
    data = {'name': '张三', 'age': 25}
    return web.json_response(data)

# 提供静态文件服务
async def handle_static(request):
    return web.FileResponse('static/index.html')

# 创建Web应用
async def create_app():
    app = web.Application()
    
    # 添加路由
    app.add_routes([
        web.get('/', handle_root),
        web.get('/api', handle_api),
        web.get('/static/{name}', handle_static)
    ])
    
    return app

# 运行Web服务器
if __name__ == '__main__':
    asyncio.run(web.run_app(create_app(), host='localhost', port=8080))

21.8.3 实施过程

  1. 安装aiohttp库。
  2. 定义处理HTTP请求的协程函数。
  3. 创建Web应用。
  4. 添加路由。
  5. 运行Web服务器。

21.8.4 最终效果

通过异步Web服务器,我们可以实现以下功能:

  • 处理HTTP请求。
  • 提供静态文件服务。
  • 实现简单的API接口。

总结

✅ 本文详细介绍了Python异步编程的基本概念和方法,包括协程、任务调度、事件循环等;学习了asyncio、aiohttp等核心库的使用;通过实战案例开发了异步HTTP客户端和异步Web服务器。

✅ 建议读者在学习过程中多练习,通过编写代码加深对知识点的理解。

相关推荐
2501_901006471 分钟前
CSS如何实现多种颜色的线性渐变_使用linear-gradient()按方向和色标填色
jvm·数据库·python
2303_821287382 分钟前
Golang怎么用embed嵌入SQL文件_Golang如何将SQL迁移文件嵌入Go程序统一管理【技巧】
jvm·数据库·python
河北之花3 分钟前
Python第一节
开发语言·python
m0_702036533 分钟前
PHP怎么处理Eloquent Attribute Harmonization属性协调_Laravel解决数据冲突【教程】
jvm·数据库·python
宠..4 分钟前
下拉列表框事件绑定
开发语言·qt·microsoft
Tairitsu_H5 分钟前
C++:优先队列的模拟实现
开发语言·c++·stl·优先队列
AI人工智能+电脑小能手6 分钟前
【大白话说Java面试题 第48题】【JVM篇】第8题:JVM 里的有几种 ClassLoader?为什么会有多种?
java·开发语言·jvm·面试
iAm_Ike6 分钟前
Redis怎样通过频道划分不同的日志级别
jvm·数据库·python
ZHW_AI课题组7 分钟前
Python调用腾讯API实现车辆号牌识别
python·ocr·腾讯云·api调用
kexnjdcncnxjs7 分钟前
CSS如何利用-nth-of-type(1)修改首个元素样式_通过位置约束精准修饰
jvm·数据库·python