ESP32升级MicroPython 1.22.2后urequests.post报内存错误16求助
问题分析与解决方案
问题概述
基于MicroPython 1.18开发的ESP32定位项目,升级到1.22.2版本后,执行urequests.post请求HTTPS地址时触发内存错误16(ENOMEM);改用HTTP请求后程序不再崩溃,但服务器返回仅支持HTTPS的错误,精简程序也无法解决问题。
核心原因
MicroPython 1.22.2的SSL/TLS栈实现相比1.18版本有更新,对内存的占用更高。ESP32的可用RAM有限(尤其是GENERIC固件默认配置下),HTTPS请求需要完成SSL握手、加密解密等操作,这些流程会占用大量内存,当剩余RAM不足以支撑这些操作时,就会触发内存不足错误。
可行解决方案
手动触发垃圾回收:在发起请求前调用
gc.collect()释放闲置内存,减少内存碎片:import gc def getLocation(): global lng,lat,acu,udf gc.collect() # 请求前回收内存 headers = {"Content-Type": "application/json"} locationStr = "https://www.googleapis.com/geolocation/v1/geolocate?key=" + APIKey try: response = urequests.post(locationStr, headers=headers, data=ujson.dumps(data)) location = ujson.loads(response.content) lng = location["location"]["lng"] lat = location["location"]["lat"] acu = location["accuracy"] print ("the current Location is lat %s, Log %s with accuracy %s" % (lat,lng,acu)) response.close() except: print("unable to read the current location %s" %OSError)分块读取响应内容:避免一次性加载整个响应到内存,改用分块读取解析,降低内存峰值:
# 替换原有的location = ujson.loads(response.content) response_data = b"" while chunk := response.read(64): # 每次读取64字节 response_data += chunk location = ujson.loads(response_data)使用精简版ESP32固件:选择MicroPython提供的
ESP32_GENERIC_SMALL固件,该固件禁用了部分非必要功能,能为用户程序预留更多RAM。优化SSL配置:指定TLS版本为TLS 1.2(Google API支持该版本),同时关闭非必要的hostname验证,减少SSL栈的内存开销:
import ssl def getLocation(): global lng,lat,acu,udf gc.collect() headers = {"Content-Type": "application/json"} locationStr = "https://www.googleapis.com/geolocation/v1/geolocate?key=" + APIKey # 配置精简SSL上下文 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx.check_hostname = False try: response = urequests.post(locationStr, headers=headers, data=ujson.dumps(data), ssl=ctx) # 后续解析代码...精简请求数据:检查
data变量的内容,去除不必要的字段,最小化发送的JSON数据大小,减少内存占用。
内容的提问来源于stack exchange,提问作者Ahmed Ali
相关产品推荐
相关产品推荐

