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

读取SML串口数据写入PostgreSQL时出现MemoryError求助

问题描述
  • 环境:Raspberry Pi 搭配USB红外抄表头读取电表SML格式数据;Python程序运行于Docker容器,校验CRC后写入远程PostgreSQL
  • 故障:容器运行约2天后触发未处理异常:
Unhandled exception in thread started by <bound method Thread._bootstrap of <Timer(Thread-40265317, initial 189230468)>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/threading.py", line 890, in _bootstrap
    self._bootstrap_inner()
  File "/usr/local/lib/python3.7/threading.py", line 914, in _bootstrap_inner
    self._set_tstate_lock()
  File "/usr/local/lib/python3.7/threading.py", line 909, in _set_tstate_lock
    _shutdown_locks.add(self._tstate_lock)
MemoryError
  • 已排查:嵌套循环、变量重置操作,怀疑日志导致内存溢出但未解决
排查与解决步骤

1. 定位Timer线程泄漏

错误来自Timer线程,Python的threading.Timer若未正确清理,会导致线程锁堆积耗尽内存:

  • 检查程序中创建Timer的逻辑:是否循环创建Timer但未对旧实例调用cancel()?是否Timer回调中递归创建新Timer,导致线程数量持续增长?
  • 在容器内执行pstree或ps aux | grep python,观察线程数是否随时间递增。

2. 优化日志输出

若未配置日志轮转,日志堆积会占用容器内存:

  • 检查Python日志配置:避免开启DEBUG级别后输出大段原始SML数据;配置日志轮转(如使用logging.handlers.RotatingFileHandler限制单文件大小)。
  • 在docker-compose.yml中添加Docker日志轮转策略:
    services:
      your-service-name:
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "3"
    

3. 修复数据库连接泄漏

若频繁创建数据库连接未关闭,会导致内存占用持续增长:

  • 检查db.py:是否每次写入都新建连接,用完后未调用close()?
  • 使用连接池(如psycopg2.pool.SimpleConnectionPool)复用连接,减少重复创建连接的内存消耗。

4. 升级Python版本

Python 3.7的threading模块存在线程锁回收的已知问题,升级到3.8+可修复部分此类问题:

  • 修改Dockerfile基础镜像,例如:
    FROM python:3.9-slim
    

5. 内存监控与泄漏定位

添加内存监控代码,定位内存增长来源:

  • 用psutil定期打印内存使用:
    import psutil
    import os
    
    def log_memory():
        proc = psutil.Process(os.getpid())
        print(f"当前内存占用: {proc.memory_info().rss / 1024 / 1024:.2f} MB")
    
  • 用tracemalloc跟踪内存分配:
    import tracemalloc
    
    tracemalloc.start()
    # 插入到程序启动处
    # ...运行一段时间后...
    snapshot = tracemalloc.take_snapshot()
    top_stats = snapshot.statistics('lineno')
    print("[TOP 10 内存占用点]")
    for stat in top_stats[:10]:
        print(stat)
    

6. 设置Docker资源限制

为容器配置内存上限,避免占用过多树莓派内存,同时便于OOM问题排查:

services:
  your-service-name:
    deploy:
      resources:
        limits:
          memory: "256M"
        reservations:
          memory: "128M"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:05:33