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

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 协程的使用

import asyncio # 定义协程asyncdefhello():print('Hello, World!')await asyncio.sleep(1)print('Hello again!')# 运行协程 asyncio.run(hello())

21.2.3 协程的暂停与恢复

import asyncio # 定义协程asyncdefcount():print('Counting...')await asyncio.sleep(1)print('Counted!')# 运行多个协程asyncdefmain():await asyncio.gather(count(), count(), count()) asyncio.run(main())

21.3 任务调度

21.3.1 创建任务

import asyncio # 定义协程asyncdefhello():print('Hello, World!')await asyncio.sleep(1)print('Hello again!')# 创建任务asyncdefmain(): task1 = asyncio.create_task(hello()) task2 = asyncio.create_task(hello())await task1 await task2 asyncio.run(main())

21.3.2 任务的取消

import asyncio # 定义协程asyncdefhello():try:print('Hello, World!')await asyncio.sleep(1)print('Hello again!')except asyncio.CancelledError:print('Task cancelled!')# 创建任务并取消asyncdefmain(): 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 任务的超时

import asyncio # 定义协程asyncdefhello():print('Hello, World!')await asyncio.sleep(2)print('Hello again!')# 任务超时asyncdefmain():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 获取事件循环

import asyncio # 获取事件循环 loop = asyncio.get_event_loop()# 定义协程asyncdefhello():print('Hello, World!')await asyncio.sleep(1)print('Hello again!')# 运行协程 loop.run_until_complete(hello())

21.4.3 事件循环的运行

import asyncio # 获取事件循环 loop = asyncio.get_event_loop()# 定义协程asyncdefhello():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的基本用法

import asyncio # 定义协程asyncdefhello():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的高级用法

import asyncio # 定义协程asyncdefhello():print('Hello, World!')await asyncio.sleep(1)print('Hello again!')# 使用Future对象asyncdefmain(): 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

pip install aiohttp 

21.6.2 发送HTTP请求

import aiohttp import asyncio # 发送GET请求asyncdeffetch(session, url):asyncwith session.get(url)as response:returnawait response.text()asyncdefmain():asyncwith aiohttp.ClientSession()as session: html =await fetch(session,'https://www.example.com')print(html) asyncio.run(main())

21.6.3 发送POST请求

import aiohttp import asyncio import json # 发送POST请求asyncdefpost_data(session, url, data):asyncwith session.post(url, data=data)as response:returnawait response.text()asyncdefmain():asyncwith 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请求

import aiohttp import asyncio import json # 发送JSON请求asyncdefpost_json(session, url, data):asyncwith session.post(url, json=data)as response:returnawait response.text()asyncdefmain():asyncwith 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 代码实现

import aiohttp import asyncio import time # 发送HTTP请求asyncdeffetch(session, url): start_time = time.time()asyncwith session.get(url)as response: text =await response.text() elapsed_time = time.time()- start_time return url,len(text), elapsed_time # 并发发送HTTP请求asyncdefmain(): urls =['https://www.example.com','https://www.google.com','https://www.github.com','https://www.python.org','https://www.djangoproject.com']asyncwith 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 代码实现

from aiohttp import web import asyncio # 处理根路径请求asyncdefhandle_root(request):return web.Response(text='Hello, World!')# 处理API接口请求asyncdefhandle_api(request): data ={'name':'张三','age':25}return web.json_response(data)# 提供静态文件服务asyncdefhandle_static(request):return web.FileResponse('static/index.html')# 创建Web应用asyncdefcreate_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服务器。
✅ 建议读者在学习过程中多练习,通过编写代码加深对知识点的理解。

Read more

Java Web 开发环境搭建:IDEA+Tomcat 安装与部署超详细教程

Java Web 开发环境搭建:IDEA+Tomcat 安装与部署超详细教程

在 Java Web 开发中,IDEA 作为主流的集成开发工具,搭配 Tomcat 轻量级 Web 服务器是入门首选。本文将基于 Java Web 基础开发要求,从 JDK 环境配置、Tomcat 安装配置、IDEA 安装、Web 项目创建,到 Tomcat 在 IDEA 中的部署运行,进行一步一图式详细讲解,零基础也能轻松上手。 一、前置准备:JDK 环境配置 Java Web 开发的核心基础是 JDK,Tomcat 和 IDEA 的运行都依赖 JDK 环境,需先完成 JDK 的安装与环境变量配置。 1. 下载与安装

By Ne0inhk
Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案

Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案 前言 在鸿蒙(OpenHarmony)生态进军政企办公领域的过程中,与现有企业信息化基础设施的深度集成是一道必答题。即便是在全连接、分布式的今天,微软的 Exchange 服务器依然是全球无数大厂与政务系统处理邮件、日历同步的核心底座。 对于习惯了简单 http.get 的移动开发者来说,Exchange Web Services(EWS)协议由于其复杂的 SOAP 封装、繁琐的 XML 数据结构以及极其严苛的身份认证机制,往往是一块难啃的“骨头”。 ews 库为 Dart 提供了成熟的、类型安全的

By Ne0inhk
本地服务器用 OpenClaw + Open WebUI 搭建企业多部门 AI 平台(附 Docker 避坑指南)

本地服务器用 OpenClaw + Open WebUI 搭建企业多部门 AI 平台(附 Docker 避坑指南)

引言: 最近在尝试使用 OpenClaw,发现这个 AI 个人助理框架非常有意思。于是团队里就有人提出:能不能为公司的多个部门,分别搭建专属的 OpenClaw 服务器? 诚然,现在有钉钉、飞书等成熟的办公软件可以接入 AI,但对于一些尚未全面普及此类协作软件的企业(或者需要绝对私有化部署的团队)来说,独立搭建一套内部 AI 门户依然是刚需。 起初,我们考虑直接让大家通过 OpenClaw 自带的 Web 界面进行跨电脑访问。但实操后发现这存在致命缺陷: 1. 权限越界:自带的 Web 端拥有底层的配置编辑权限,暴露给普通员工极其不安全。 2. 无法溯源:多终端共用一个 Web 界面,根本无法追溯对话是由谁发起的。 3. 缺乏隔离:无法按部门精细化分配 API 额度或限制特定部门只能访问特定的 OpenClaw 节点,无法实现业务隔离。 为了解决这些痛点,我们最终确定了这套架构方案:

By Ne0inhk
Flutter for OpenHarmony: Flutter 三方库 fixnum 解决鸿蒙 Web 与原生端 64 位大整数精度失真难题(精准计算护卫)

Flutter for OpenHarmony: Flutter 三方库 fixnum 解决鸿蒙 Web 与原生端 64 位大整数精度失真难题(精准计算护卫)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在进行 OpenHarmony 的跨平台开发时,你可能会遇到一个诡异的 Bug:同样的 64 位长整数(如 Int64),在鸿蒙原生(Native)模式下运行正常,但编译为 Flutter Web 模式在浏览器运行时,数值却发生了精度漂移或溢出。 1. 产生原因:JavaScript 原生的数字类型实质上是 64 位浮点数,它能安全表示的最大整数只有 53 位( 2 53 − 1 2^{53}-1 253−1)。 2. 后果:大额订单 ID、高精度的金融分位值、或是底层硬件的 64 位地址位,在

By Ne0inhk