Python异步发送遥测数据至Azure IoT Hub:无需等待但数据未发送
问题解决思路及修改代码
核心问题分析
你的代码里有几个关键问题导致初始数据发不出去,甚至后续发送也不稳定:
- 发送函数捕获所有异常但无日志,根本不知道哪里出错(比如连接字符串无效、网络问题、消息格式错误)
- 每次发送都新建
IoTHubSession,频繁创建销毁连接会导致发送失败概率飙升 - 初始任务创建后,若循环计算速度快,第一次判断
task1.done()时任务可能还在运行,你无法得知任务是否成功
修改后的代码
1. 优化发送函数(加日志+复用会话)
import logging # 配置日志,方便排查问题 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) async def send_telemetry_to_iot_hub(session, data): try: msg = Message(data, "utf-8", "application/json") await session.send_message(msg) logger.info(f"数据发送成功: {data}") return True except Exception as e: logger.error(f"数据发送失败 [{data}]: {str(e)}") return False
2. 优化主逻辑(复用会话+正确处理任务状态)
async def main(): CONNECTION_STRING = '******' # 提前创建一次会话,全程复用,避免重复建立连接 async with IoTHubSession.from_connection_string(CONNECTION_STRING) as session: # 启动初始发送任务 send_task = asyncio.create_task(send_telemetry_to_iot_hub(session, 'start')) while True: result = calculate_result() print(result) # 检查发送任务是否完成 if send_task.done(): # 获取任务执行结果(因为发送函数返回bool,不会抛出异常) send_success = await send_task # 可选:如果上一次发送失败,可以选择重试当前result或者跳过 # if not send_success: # send_task = asyncio.create_task(send_telemetry_to_iot_hub(session, result)) # else: send_task = asyncio.create_task(send_telemetry_to_iot_hub(session, result)) # 给事件循环留处理后台任务的时间,避免循环太密集占用CPU await asyncio.sleep(0.01) asyncio.run(main())
关键优化点说明
- 日志排查:通过日志能直接看到初始发送失败的具体原因,比如连接字符串错误、IoT Hub设备权限未配置等
- 会话复用:避免每次发送都重新建立连接,大幅提升发送稳定性和效率
- 任务状态处理:循环持续检查发送任务状态,一旦完成就立刻处理结果并启动下一次发送,不会遗漏发送时机
- CPU占用优化:添加微小延迟,让事件循环有时间处理后台发送任务,避免任务一直处于pending状态
内容的提问来源于stack exchange,提问作者SaibotDev
相关产品推荐
相关产品推荐

