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

如何从Node-RED向树莓派终端发送CTRL+C终止Python脚本?

如何从Node-RED优雅终止树莓派上的Python GPIO脚本(触发KeyboardInterrupt)

我明白你的需求——给高中生做教程,得让Python脚本在终止时优雅清理GPIO,而不是硬杀导致引脚状态异常。你之前用kill/killall的问题在于默认信号不会触发KeyboardInterrupt,而管道发$'\cc'又有权限问题,下面给你两个可靠的解决方案:

方法一:通过PID发送SIGINT信号(完全模拟CTRL+C,推荐)

这个方法直接对应你想要的“按下CTRL+C”的行为,步骤很清晰:

  1. 在Node-RED中记录脚本PID
    配置EXEC节点运行你的脚本时,找到并勾选Append PID to msg.payload选项。这样脚本启动后,msg.payload会返回进程的PID(比如类似1234的数字)。

  2. 存储PID供后续使用
    把这个PID存到Node-RED的Flow/Global变量里(用Change节点就能实现),或者用Context节点暂存,方便后面终止脚本时调用。

  3. 发送SIGINT信号终止脚本
    当需要停止脚本时,用另一个EXEC节点执行命令:

    sudo kill -SIGINT <你存储的PID>
    

    这里的-SIGINT是关键——它就是CTRL+C对应的信号,会触发你脚本里的except KeyboardInterrupt块,自动执行pwm.stop()和GPIO.cleanup()。

方法二:修改Python脚本,兼容更多终止信号

如果觉得管理PID有点麻烦,可以修改你的Python脚本,让它不仅响应SIGINT,还能捕获默认的kill信号(SIGTERM),这样即使普通的kill/killall命令也能触发清理:

修改后的脚本示例:

import RPi.GPIO as GPIO
import time
import signal
import sys

pwmPin = 18
ledPin = 23
butPin = 17
dc = 95

# 统一的清理函数
def cleanup(signal_num, frame):
    pwm.stop()
    GPIO.cleanup()
    print("GPIO cleaned up, exiting gracefully")
    sys.exit(0)

# 注册信号处理:同时监听SIGINT(CTRL+C)和SIGTERM(默认kill信号)
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)

GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)
GPIO.setup(pwmPin, GPIO.OUT)
pwm = GPIO.PWM(pwmPin, 50)
GPIO.setup(butPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.output(ledPin, GPIO.LOW)
pwm.start(dc)

print("Press CTRL+C to exit, or use 'kill <PID>' to stop")

try:
    while 1:
        if GPIO.input(butPin):
            pwm.ChangeDutyCycle(dc)
            GPIO.output(ledPin, GPIO.LOW)
        else:
            pwm.ChangeDutyCycle(100-dc)
            GPIO.output(ledPin, GPIO.HIGH)
            time.sleep(0.075)
            GPIO.output(ledPin, GPIO.LOW)
            time.sleep(0.075)
except Exception as e:
    # 捕获意外错误也执行清理
    print(f"Unexpected error: {str(e)}")
    cleanup(None, None)

改完之后,你用sudo kill <PID>或者sudo killall python就能触发清理逻辑了,不用特意指定信号。

为什么你之前的尝试失败了?

  • kill/killall默认发送的是SIGTERM信号,你的原脚本没有捕获这个信号,所以直接终止进程,不会执行清理代码。
  • echo $'\cc' | sudo python Documents/python/blinker.py的权限错误是因为脚本没有可执行权限(可以用chmod +x Documents/python/blinker.py解决),但即使解决了权限问题,这种方式是给脚本的标准输入发EOF,不是真正的SIGINT,可靠性不如直接发送信号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:11:06