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

如何让Python主脚本执行Shell脚本时不阻塞UDP消息接收

解决方案

核心问题分析

你的Python主控脚本被Shell脚本卡住,是因为subprocess.call()是阻塞式调用——它会等待子进程(Shell脚本)完全执行结束后才继续运行,而LED播放脚本是持续循环的进程,导致主控脚本无法继续接收UDP指令。

关键修改点

  • 改用subprocess.Popen()替代subprocess.call(),启动子进程后立即返回,不阻塞主控脚本
  • 维护全局变量跟踪当前运行的LED进程,收到新指令时先终止旧进程再启动新进程
  • 优化Shell脚本,避免重复编译(make操作仅需在代码更新时执行)

修改后的Python主控脚本

import socket
import subprocess

UDP_IP = "192.168.50.3"
UDP_PORT = 5005
current_led_process = None  # 跟踪当前运行的LED进程

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print(f"received message: {data}")

    # 终止当前运行的LED进程(如果存在)
    if current_led_process is not None:
        # 先尝试优雅终止,超时则强制杀死
        current_led_process.terminate()
        try:
            current_led_process.wait(timeout=2)
        except subprocess.TimeoutExpired:
            current_led_process.kill()
        current_led_process = None

    # 根据指令启动对应播放脚本
    if data == b'Hello, World!':
        current_led_process = subprocess.Popen(['sh', './test.sh'])
    elif data == b'Hello, Bozo!':
        current_led_process = subprocess.Popen(['sh', './test1.sh'])

优化后的Shell脚本(以test.sh为例)

#!/bin/sh
# 终止旧的LED进程(与Python端操作形成双重保险)
sudo pkill -9 -f led-image-viewer

# 仅在首次运行或代码更新时执行编译,日常运行可注释该行
# cd /home/maxi/rpi-rgb-led-matrix/utils && make led-image-viewer

cd /home/maxi/rpi-rgb-led-matrix/utils
sudo ./led-image-viewer -C tenor.gif --led-rows=64 --led-cols=64 --led-slowdown-gpio=2

额外注意事项

  • 确保Python脚本执行用户拥有sudo免密权限,可修改/etc/sudoers配置,让该用户无需输入密码即可运行pkill和led-image-viewer命令,避免因密码输入导致进程卡住
  • 若pkill匹配进程不准确,可调整匹配参数(如使用更精准的进程名或PID)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:15:38