使用paho-mqtt向AWS IoT Core发布数据报FileNotFoundError如何解决
故障根因
你遇到的FileNotFoundError: [Errno 2] No such file or directory和AWS IoT Thing的证书有效性、策略配置完全无关,本质是Python运行时无法通过你填写的相对路径定位到证书文件。你之前排查斜杠、文件名、扩展名的方向没错,但忽略了Python相对路径的基准规则:代码里写的相对路径,基准是执行Python命令时终端所处的工作目录,不是code.py脚本自身所在的目录。
举个例子:如果你在C:\Users\你的用户名路径下执行命令python C:\Users\你的用户名\PyProj\projfolder\code.py,那代码里写的certs/AmazonRootCA1.pem实际会去找C:\Users\你的用户名\certs\AmazonRootCA1.pem,和你存放在项目目录下的certs文件夹位置完全不匹配,自然报找不到文件。
修复步骤
1. 先解决证书路径问题
两种稳妥的修复方案选其一即可,优先选第二种,不受执行路径影响:
- 方案一:直接写证书的绝对路径
Windows系统下路径字符串前加r避免斜杠转义,示例:ca_path = r"C:\Users\你的用户名\PyProj\projfolder\certs\AmazonRootCA1.pem" cert_path = r"C:\Users\你的用户名\PyProj\projfolder\certs\a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_certificate.pem.crt" key_path = r"C:\Users\你的用户名\PyProj\projfolder\certs\a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_private.pem.key" - 方案二:基于脚本自身位置动态拼接路径(通用推荐)
不管你在哪个目录执行脚本,都能准确定位到同目录下的certs文件夹:import os # 获取当前code.py文件所在的绝对目录 script_dir = os.path.dirname(os.path.abspath(__file__)) ca_path = os.path.join(script_dir, "certs/AmazonRootCA1.pem") cert_path = os.path.join(script_dir, "certs/a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_certificate.pem.crt") key_path = os.path.join(script_dir, "certs/a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_private.pem.key")
验证方式:打印三个路径,直接复制到文件资源管理器地址栏访问,能正常打开对应证书文件就说明路径配置正确。
2. 修复代码里的其他隐藏问题
路径问题解决后,你现有代码还有两个必踩的坑,提前修复避免后续调不通:
- 不能直接给
publish()传pandas DataFrame对象:MQTT只支持传输字符串/字节类型的负载,你需要先把DataFrame序列化成JSON、CSV等字符串格式,示例:# 把DataFrame转成JSON字符串 payload = dataframe.to_json(orient="records") - 不能刚调用
connect()就立刻发消息:paho-mqtt的connect()是异步非阻塞方法,调用后不会等TLS握手、MQTT连接完成就返回,立刻发消息会因为连接未建立导致发送失败。简单测试场景可以加短延时等待连接建立,正式场景建议用连接成功回调触发发布逻辑,或者启动后台网络循环。
可直接运行的参考代码
import paho.mqtt.client as mqtt import os import time import json import pandas as pd # 基础配置 clientID = "iotconsole-somenumber-0" broker = "alphanumeric-ats.iot.us-west-1.amazonaws.com" port = 8883 topic = "awsiot_test" # 动态拼接证书路径 script_dir = os.path.dirname(os.path.abspath(__file__)) ca_path = os.path.join(script_dir, "certs/AmazonRootCA1.pem") cert_path = os.path.join(script_dir, "certs/a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_certificate.pem.crt") key_path = os.path.join(script_dir, "certs/a0c94969f1e7d914d6fe54425d772e8d4611a4710d460e9f56374ea0afd4f67f_private.pem.key") # 初始化客户端并配置TLS pub = mqtt.Client(clientID) pub.tls_set(ca_path, certfile=cert_path, keyfile=key_path) # 启动后台网络循环,等待连接建立 pub.connect(broker, port) pub.loop_start() time.sleep(2) # 读取txt数据转DataFrame,替换成你自己的文件路径和读取逻辑 df = pd.read_csv(os.path.join(script_dir, "your_source_data.txt")) payload = df.to_json(orient="records") # 发布消息 pub.publish(topic, payload, qos=1) time.sleep(1) # 清理资源退出 pub.loop_stop() pub.disconnect()
额外排查提示:如果路径修正后出现SSL握手、权限拒绝类的报错,再去检查AWS IoT侧的证书是否激活、是否绑定了允许发布的策略、client ID是否和策略匹配即可,你当前遇到的报错和这些配置没有关系。
内容的提问来源于stack exchange,提问作者AV111
相关产品推荐
相关产品推荐

