You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Microdot异步Web API与其他asyncio函数同时运行?

解决Microdot与异步thermostat协程并发运行的问题

问题根源

你遇到的RuntimeWarning: coroutine 'Microdot.start_server' was never awaited警告,核心原因是microdot_asyncio的app.run()是阻塞式启动方法,它会自行创建并运行事件循环,无法在已有的asyncio事件循环中与其他协程兼容。正确的做法是使用app.start_server()协程,让它在共享事件循环中被await,从而实现和run_thermostat()的并发。

修正后的代码

from microdot_asyncio import Microdot
import asyncio

class Thermostat:
    def __init__(self):
        self.current_temp = 0
        self.target_temp = 0

    async def async_main(self):
        # 同时启动web服务和thermostat循环
        await asyncio.gather(
            self.start_web_server(),
            self.run_thermostat(),
        )

    # 改为异步函数,使用start_server协程替代阻塞的run()
    async def start_web_server(self):
        await app.start_server(port=5000)  # 可根据需求指定端口

    async def read_temperature(self):
        # 模拟读取传感器温度
        self.current_temp = 15

    def set_target_temp(self, temp):
        self.target_temp = temp

    def control_heating(self):
        if self.current_temp < self.target_temp:
            print("Starting heating system")
        else:
            print("Stopping heating system")

    async def run_thermostat(self):
        while True:
            await self.read_temperature()  # 使用self调用类内方法,避免依赖全局实例
            self.control_heating()
            await asyncio.sleep(1)

# 初始化Microdot应用
app = Microdot()

@app.route('/set_target_temp')
def set_target_temp(request):
    target_temp = int(request.args['temp'])
    thermostat.set_target_temp(target_temp)
    return f"Target temperature set to {target_temp}"

# 创建thermostat实例
thermostat = Thermostat()

# 启动主协程
if __name__ == "__main__":
    asyncio.run(thermostat.async_main())

关键修改说明

  1. 替换app.run()为app.start_server():
    app.start_server()是异步协程,需要被await,能和其他协程在同一个事件循环中并发执行;而app.run()会阻塞并独占事件循环,导致其他协程无法正常运行。

  2. 使用asyncio.gather()并发执行协程:
    asyncio.gather()可以将多个协程打包,让它们在事件循环中同时运行,直到所有协程完成(这里两个都是无限循环,会持续运行)。

  3. 改用asyncio.run()启动主协程:
    这是Python 3.7+推荐的asyncio启动方式,它会自动创建、管理事件循环,避免手动操作循环带来的兼容性问题。

  4. 类内方法调用改为self:
    run_thermostat中使用self.read_temperature()替代全局实例调用,让代码更健壮,消除对全局变量的依赖。

运行验证

启动代码后,你可以:

  • 访问http://localhost:5000/set_target_temp?temp=20设置目标温度
  • 控制台会每秒输出加热系统状态,同时web服务可正常响应请求

内容的提问来源于stack exchange,提问作者yaml01H2S04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:40:37