Python多进程执行完毕后随机挂起问题求助(树莓派环境)
树莓派Python子进程挂起问题解决思路
核心问题:树莓派4(2GB)上的Python脚本,在启动子进程执行相机拍照、存图、数据库插入任务后,进程随机挂起,join()超时、kill()等方法无法终止进程。
排查与解决步骤
1. 先定位挂根因
- 用
top或htop查看挂起进程的状态:如果状态是D(不可中断睡眠),说明进程卡在硬件IO操作上(比如相机读取、磁盘写入、数据库连接) - 查看系统日志
/var/log/syslog和dmesg,找相机、存储、数据库相关的报错信息
2. 修复函数里的隐藏问题
- 变量未传递:原代码中
processo_automatico直接用主进程的peso,子进程不会继承这个变量,会抛出未定义错误,可能导致进程异常挂起。必须通过参数传递:# 主进程启动时传参 processo = multiprocessing.Process(target=processo_automatico, args=(peso,)) # 修改函数定义 def processo_automatico(peso): now = str(datetime.now()).replace(":", "-") foto = CAMERA.read_camera() cv2.imwrite(f"/var/www/html/{now}.png", foto) DB.insert(f"/var/www/html/{now}.png", peso) - 资源未释放:相机、数据库连接必须在子进程结束前明确关闭:
- 如果用opencv的VideoCapture,拍照后调用
CAMERA.release() - 数据库操作完成后,关闭连接(比如
DB.close()),避免持锁导致进程无法退出
- 如果用opencv的VideoCapture,拍照后调用
3. 优化进程管理逻辑
- 用
terminate()替代直接kill():terminate()发送SIGTERM信号尝试优雅终止,失败再用kill()强制杀死 - 避免主进程长期阻塞,同时限制并发:
while True: time.sleep(1) peso = getPeso() if peso > 900: # 清理残留的挂起进程 if 'processo' in locals() and processo.is_alive(): processo.terminate() processo.join(timeout=5) if processo.is_alive(): processo.kill() # 启动新进程 processo = multiprocessing.Process(target=processo_automatico, args=(peso,)) processo.start() # 等待进程结束,超时处理 processo.join(timeout=15) if processo.is_alive(): errore_cicalino() processo.terminate() processo.join(timeout=5) if processo.is_alive(): processo.kill() andare()
4. 替换阻塞式操作
- 相机读取改成带超时的非阻塞方式:比如用opencv的
grab()尝试捕获帧,超时则放弃,避免卡死 - 数据库插入设置超时时间:如果用SQLite,确保操作不会因为锁等待挂起;如果是远程数据库,设置连接和查询超时
5. 树莓派硬件适配优化
- 2GB内存有限,改用
multiprocessing.Pool复用进程,减少进程创建销毁的开销和内存碎片 - 关闭不必要的后台服务(比如蓝牙、VNC),释放系统资源,降低硬件IO冲突概率
内容的提问来源于stack exchange,提问作者Andrea marini
相关产品推荐
相关产品推荐

