Ubuntu Python异步编程入门
Ubuntu 下 Python 异步编程入门指南

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
一 环境准备
想在 Ubuntu 上玩转异步编程,首先得把环境搭好。这里有几个关键步骤:
- Python 版本选择:强烈建议使用 Python 3.7 或更高版本。如果你的系统版本比较旧,可以通过添加 deadsnakes PPA 源来安装新版本。别忘了创建虚拟环境,它能帮你把项目依赖隔离得干干净净。
- 安装与准备
sudo apt update && sudo apt install -y python3 python3-pipsudo add-apt-repository ppa:deadsnakes/ppasudo apt install -y python3.10 python3.10-venv
- 创建虚拟环境
python3.10 -m venv .venvsource .venv/bin/activate
- 安装与准备
- 常用异步库
pip install aiohttp httpx
简单说明一下:asyncio 模块从 Python 3.4 开始引入,而我们现在熟悉的 async/await 语法则在 3.5 版本稳定下来。之所以推荐 3.7+,是因为从这个版本开始,提供了像 asyncio.run() 这样更简洁、更友好的程序入口,对新手来说门槛低了不少。
二 核心概念与第一个异步程序
理解了下面几个概念,异步编程的大门就算推开一半了。
- 关键概念
- 事件循环 (Event Loop):它是整个异步运行的心脏,负责调度和切换各个协程。
- 协程 (Coroutine):用
async def定义的函数,它的妙处在于能在等待时主动“让出”控制权。 - 任务 (Task):可以理解为对协程的包装,交给事件循环去并发调度。
- 可等待对象 (Awaitable):这是一个统称,协程、任务和 Future 都属于此类。
- 最小示例
- 顺序执行:让两个协程A和B依次运行,分别等待1秒和2秒,总耗时自然是3秒左右。
-
import asyncio async def say_delay(name, sec): print(f\"[{name}] start\") await asyncio.sleep(sec) print(f\"[{name}] done\") async def main(): await say_delay(“A”, 1) await say_delay(“B”, 2) if __name__ == “__main__”: asyncio.run(main())
-
- 并发执行:使用
asyncio.create_task将协程包装成任务,让它们并发跑起来。这样,总耗时就取决于最慢的那个任务,大约2秒。-
import asyncio async def say_delay(name, sec): print(f\"[{name}] start\") await asyncio.sleep(sec) print(f\"[{name}] done\") async def main(): t1 = asyncio.create_task(say_delay(“A”, 1)) t2 = asyncio.create_task(say_delay(“B”, 2)) await t1; await t2 if __name__ == “__main__”: asyncio.run(main())
-
- 顺序执行:让两个协程A和B依次运行,分别等待1秒和2秒,总耗时自然是3秒左右。
- 运行方式
- 记住这个标准流程:用
asyncio.run(main())作为程序入口;在协程内部,用await来等待其他可等待对象;想实现并发,就用create_task把协程调度成任务。
- 记住这个标准流程:用
三 实战 异步 HTTP 请求
理论懂了,来点实际的。异步编程最常见的场景之一就是并发处理网络请求。
- 使用 aiohttp 并发抓取多个站点
-
import asyncio, aiohttp async def download_site(url, session): async with session.get(url) as resp: print(f\"{url} -> {resp.status}\") async def main(): urls = [“https://example.com”, “https://example.org”] async with aiohttp.ClientSession() as session: tasks = [download_site(u, session) for u in urls] await asyncio.gather(*tasks) if __name__ == “__main__”: asyncio.run(main())
-
- 使用 httpx(支持同步/异步)
- 安装:
pip install httpx -
import asyncio, httpx async def fetch(url): async with httpx.AsyncClient() as client: r = await client.get(url) return r.status_code async def main(): urls = [“https://www.example.com”, “https://www.python.org”, “https://www.github.com”] results = await asyncio.gather(*[fetch(u) for u in urls]) for u, s in zip(urls, results): print(u, s) if __name__ == “__main__”: asyncio.run(main())
- 安装:
四 常见陷阱与最佳实践
掌握了基本操作,还得了解哪些坑要避开,以及如何写出更健壮的代码。
- 避免阻塞调用:这是新手最容易犯的错误。在协程里,千万别用
time.sleep、requests.get这类会阻塞整个线程的 API。正确的做法是换成await asyncio.sleep()和异步 HTTP 客户端(比如 aiohttp 或 httpx)。 - 控制并发度:无限制地并发请求,很容易把目标服务器或者自己的机器资源压垮。这时候,
asyncio.Semaphore信号量就是你的限流神器。-
import asyncio async def worker(i, sem): async with sem: print(f\"worker-{i} working\") await asyncio.sleep(1) async def main(): sem = asyncio.Semaphore(5) # 最多同时 5 个 await asyncio.gather(*[worker(i, sem) for i in range(20)]) asyncio.run(main())
-
- 超时与容错:网络世界充满不确定性。对于可能很慢或者不可靠的操作,一定要用
asyncio.wait_for设置超时,并妥善捕获异常。-
import asyncio async def job(): await asyncio.sleep(5) return “ok” async def main(): try: r = await asyncio.wait_for(job(), timeout=2) print(r) except asyncio.TimeoutError: print(“timeout”) asyncio.run(main())
-
- 任务生命周期:用
create_task创建任务后,务必记得通过await或者在gather中等待它完成。否则,主协程一旦提前退出,那些还没跑完的任务就会被无情取消。 - 何时使用异步 vs 线程/进程
- I/O 密集型(比如网络请求、磁盘读写、数据库操作):这是异步编程的主场,优先选择 asyncio。
- CPU 密集型(比如大量数学计算):异步在这里帮不上忙,反而可能因为事件循环被阻塞而变慢。这种情况下,应该优先考虑
multiprocessing或者concurrent.futures.ProcessPoolExecutor。当然,也可以在事件循环里用run_in_executor,把阻塞函数丢到线程池或进程池里去执行。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
怎么利用 System.err 输出错误流并在控制台中以醒目的颜色标记(取决于终端)
怎么利用 System err 输出错误流并在控制台中以醒目的颜色标记(取决于终端) System err 默认行为不带颜色,终端是否显示颜色取决于自身支持 首先得明确一点:System err 本质上只是 Ja va 标准库里的一个 PrintStream 对象。它本身并不负责“颜色”这种花哨的玩
如何在 Java 中使用 ThreadLocal.remove() 确保在线程池复用场景下不会发生数据污染
如何在 Ja va 中使用 ThreadLocal remove() 确保在线程池复用场景下不会发生数据污染 说到线程池和 ThreadLocal 的搭配使用,一个看似不起眼、实则极易“踩坑”的细节就是数据清理。想象一下,你精心设计的线程池正在高效运转,却因为某个任务留下的“数据尾巴”,导致后续任务
怎么利用 Arrays.asList() 转换出的“受限列表”理解其对 add() 等修改操作的限制
Arrays asList():一个“受限”但实用的列表视图 在Ja va开发中,Arrays asList()是一个高频使用的方法,但你是否真正了解它返回的是什么?一个常见的误解是,它直接生成了一个标准的ArrayList。事实并非如此。 简单来说,Arrays asList()返回的并非我们熟悉
如何在 Java 中利用 try-catch 实现对“软错误”的平滑感知与非侵入式监控日志记录
如何在 Ja va 中利用 try-catch 实现对“软错误”的平滑感知与非侵入式监控日志记录 在 Ja va 开发中,我们常常会遇到一些“软错误”——它们不会让程序直接崩溃,却可能悄悄影响业务的正确性或用户体验。比如,调用第三方 API 时返回了空响应、缓存查询未命中、配置文件里某个非关键项缺失
Django怎么防止Celery任务重复执行_Python结合Redis实现分布式锁
Django怎么防止Celery任务重复执行:Python结合Redis实现分布式锁 你遇到过吗?明明只发了一次任务,后台却执行了两次。这不是代码写错了,而是分布式环境下一个经典的老朋友:多个worker同时抢到了同一个活儿。 为什么Celery任务会重复执行 问题的根源在于竞争。想象一下,多个Ce
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

