MicroPython 没有真正的多线程,仅支持 uasyncio 并发;uasyncio.run() 阻塞运行至任务结束,需用 create_task() 启动后台协程并配合 sleep_ms() 让出控制权,且版本兼容性差异大。

MicroPython 有真正的多线程吗?
没有。uasyncio 是 MicroPython 唯一被广泛支持的并发方案,thread 模块在绝大多数端口(如 ESP32 的默认固件、RP2040)里根本不存在或被禁用。硬上 threading 会直接报 ImportError: no module named 'threading' 或触发看门狗复位。
原因很实际:MicroPython 运行在资源极受限的 MCU 上,没有 MMU,无法安全调度抢占式线程;加锁、上下文切换开销也远超 RAM 和 CPU 承受能力。
所以别搜“MicroPython 多线程教程”——那基本是拿 CPython 经验硬套,结果就是卡死或内存溢出。
uasyncio.run() 为什么总卡住不返回?
因为 uasyncio.run() 是阻塞式入口,它会一直运行直到所有任务完成并事件循环关闭。但你在裸机环境里写的任务,往往没显式退出逻辑,比如:
立即学习“Python免费学习笔记(深入)”;
import uasyncio as asyncio<br>async def blink():<br> while True:<br> led.on()<br> await asyncio.sleep(0.5)<br> led.off()<br> await asyncio.sleep(0.5)<br>asyncio.run(blink()) # ← 永远不会执行到这行后面
常见错误场景:
- 把
uasyncio.run()当成普通函数调用,期待它“启动后就继续往下走” - 在 REPL 中反复执行
uasyncio.run(),导致事件循环已运行却强行再启,报RuntimeError: event loop already running - 忘记加
await asyncio.sleep_ms(1)类似让步语句,导致单个协程霸占 CPU,其他任务饿死
如何让多个协程真正“同时”跑起来?
靠 asyncio.create_task() 启动后台任务,再用 await asyncio.sleep() 或 await asyncio.sleep_ms() 主动交出控制权。关键不是“写 async”,而是“让出时机”。
示例:两个 LED 独立闪烁,频率不同
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
import uasyncio as asyncio<br>from machine import Pin<br><br>led_a = Pin(2, Pin.OUT)<br>led_b = Pin(4, Pin.OUT)<br><br>async def flash(pin, interval_ms):<br> while True:<br> pin.value(not pin.value())<br> await asyncio.sleep_ms(interval_ms) # ← 必须有这一句<br><br>async def main():<br> # 并发启动两个任务<br> asyncio.create_task(flash(led_a, 300))<br> asyncio.create_task(flash(led_b, 700))<br> # 主协程不能空转,否则第二个任务可能没机会调度<br> await asyncio.sleep(60) # 运行一分钟<br><br>asyncio.run(main())
注意点:
-
create_task()立即调度,但不会阻塞;await才真正让其他任务轮转 -
sleep_ms()比sleep(0.3)更精准、开销更低,适合 MCU - 避免在协程里调用阻塞函数(如
time.sleep()、串口read()无超时),会拖垮整个事件循环
uasyncio 版本和硬件兼容性怎么查?
MicroPython 不同版本、不同芯片端口的 uasyncio 差异很大:ESP32-C3 固件自带 v3,而旧版 ESP8266 只有 v1.4,连 create_task() 都没有,得用 asyncio.ensure_future()。
检查方法很简单:
>>> import uasyncio<br>>>> uasyncio.__version__<br>'3.0'
常见兼容问题:
- v1.x:没有
create_task(),用asyncio.ensure_future(coro) - v2.x 起:支持
create_task(),但部分板子(如某些 RP2040 构建)仍缺wait_for()或timeout() - 所有版本都不支持
asyncio.gather()的return_exceptions=True参数,出错就崩 - 别试图在
uasyncio里用async with或async for—— 大多数固件没实现相应协议
最稳的做法:始终用 micropython -m upip install micropython-uasyncio 安装官方维护的独立包,而不是依赖固件内置版本。
协程调度本身不难,难的是记住你面对的不是 Linux,而是一块 2MB Flash、264KB RAM、没虚拟内存、没信号、没进程树的芯片。任何“理所当然”的假设,都可能变成一小时调试。


















