如何让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
相关产品推荐
相关产品推荐

