




















Python 的协程模型和 JavaScript 的 async/await 非常像,因为:
Python 的 asyncio 在设计上大量借鉴了 JavaScript 的 Promise + Event Loop 模型。
尤其是:
| JavaScript | Python |
|---|---|
| async function | async def |
| await | await |
| Promise | Future / Task |
| Event Loop | Event Loop |
| 单线程异步 IO | 单线程异步 IO |
所以如果你熟悉 JS,再学 Python 协程会轻松很多。
async function hello() {
console.log("start");
await fetch("/api");
console.log("end");
}
import asyncio
async def hello():
print("start")
await asyncio.sleep(1)
print("end")
结构几乎一样。
本质都是:
遇到 await
↓
暂停当前函数
↓
把控制权交回事件循环
↓
等待 IO 完成
↓
恢复执行
这就是:
协作式并发(cooperative concurrency)
JavaScript:
async function f() {}
Python:
async def f():
pass
它们都:
这是两者一个重要区别。
async 函数返回:
Promise
例如:
async function f() {
return 123;
}
console.log(f())
输出:
Promise { 123 }
async def 返回:
coroutine object
例如:
async def f():
return 123
print(f())
输出:
<coroutine object>
JS:
await fetch(...)
Python:
await session.get(...)
都表示:
“这里可能要等待,先切出去执行别的任务。”
浏览器 / Node.js:
call stack
task queue
microtask queue
event loop
ready queue
selector/epoll
callback queue
task scheduler
思想高度一致:
谁 IO 完成了
↓
恢复谁执行
const p = fetch("/api");
p 是 Promise。
task = asyncio.create_task(work())
task 是 Task。
都表示:
一个未来会完成的异步任务
await Promise.all([
fetch("/a"),
fetch("/b")
])
await asyncio.gather(
fetch_a(),
fetch_b(),
)
几乎一模一样。
JS 的 async/await:
Python:
这些概念暴露更多。
所以 Python asyncio:
这是和 JS 最大的历史区别。
JavaScript async:
Promise 驱动
而 Python 协程:
generator/yield 演化而来
所以 Python 有:
这些底层机制。
JS 没这么复杂。
早期 Python:
@asyncio.coroutine
def f():
yield from ...
后来才有:
async def
await
所以 Python 协程体系有明显演化痕迹。
而 JS 基本一步到位:
callback
→ Promise
→ async/await
因为:
Web 服务本质是 IO 密集
大量时间在:
async 模型非常适合。
所以:
都 heavily async。
Python:
async != 多线程
它默认还是:
单线程事件循环
因此:
await cpu_heavy()
不会 magically 并行。
CPU 密集任务仍需要:
这一点 JS 也类似。
你会发现:
| JS 概念 | Python 概念 |
|---|---|
| Promise | Future |
| Promise.all | asyncio.gather |
| setTimeout | asyncio.sleep |
| async function | async def |
| await | await |
| Event Loop | Event Loop |
真正需要重新适应的是:
Python coroutine object / Task / Future 的区别
这比 JS 更细。
JS:
fetch("/api")
会立刻开始请求。
Python:
coro = fetch()
很多时候:
只是创建 coroutine object
并不会立刻执行
必须:
await coro
或者:
asyncio.create_task(coro)
才真正调度。
这是很多 JS 开发者刚转 Python 时最容易踩坑的地方。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。