树莓派项目:如何在Python主脚本启停需sudo权限的子脚本?
解决方案
用subprocess模块管理子进程(推荐)
os.system无法直接控制已启动的后台进程,改用subprocess.Popen可以获取子进程对象,随时终止它:
主脚本代码
import subprocess # 启动ringlight.py后台进程 ring_process = subprocess.Popen(["sudo", "python", "ringlight.py"]) # 需要终止补光灯时调用以下代码 # 优雅终止(推荐,给进程留清理资源的时间) ring_process.terminate() # 若优雅终止无效,可强制杀死进程 # ring_process.kill()
ringlight.py优化(可选)
为了让补光灯退出前能正确关闭灯光、清理NeoPixel资源,可添加信号捕获逻辑:
import signal import sys from rpi_ws281x import Adafruit_NeoPixel # 初始化NeoPixel环形灯(根据你的硬件参数调整) LED_COUNT = 16 LED_PIN = 18 strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN) strip.begin() def cleanup_and_exit(signum, frame): # 关闭灯光并退出 strip.fill(0) strip.show() sys.exit(0) # 注册SIGTERM信号处理(对应主脚本的terminate()调用) signal.signal(signal.SIGTERM, cleanup_and_exit) # 补光灯运行逻辑示例(比如保持常亮) while True: strip.fill((255, 255, 255)) strip.show()
免密sudo配置(避免输入密码)
如果启动时需要手动输入sudo密码,可配置免密权限简化操作:
- 执行
sudo visudo - 在文件末尾添加一行(替换为你的实际文件路径):
pi ALL=(ALL) NOPASSWD: /usr/bin/python /home/pi/ringlight.py
替代方案:文件信号控制
如果不想用信号机制,可通过临时文件作为终止标记:
ringlight.py代码
import os import sys import time from rpi_ws281x import Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 18) strip.begin() TERM_MARKER = "/tmp/ringlight_stop" # 清除旧的终止标记 if os.path.exists(TERM_MARKER): os.remove(TERM_MARKER) while True: if os.path.exists(TERM_MARKER): # 清理灯光并退出 strip.fill(0) strip.show() os.remove(TERM_MARKER) sys.exit(0) # 补光灯运行逻辑 strip.fill((255, 255, 255)) strip.show() time.sleep(0.1)
主脚本终止代码
# 创建终止标记文件触发退出 open("/tmp/ringlight_stop", "w").close()
内容的提问来源于stack exchange,提问作者Jarhara
相关产品推荐
相关产品推荐

