【问题标题】:Can't quit a running python script无法退出正在运行的 python 脚本
【发布时间】:2016-12-30 15:05:08
【问题描述】:

我刚开始学习使用 python 进行 Raspberry Pi 开发,并在我的面包板上设置了一个简单的 RGB LED 电路,然后我将它连接到 Pubnub 以通过我构建的一个小 Web 界面控制它,该界面只发送一个方法名称和 RGB 值python脚本订阅特定频道的Pubnub。

from pubnub import Pubnub
import RPi.GPIO as G
import time

pubnub = Pubnub(publish_key="****", subscribe_key="****")
def callback(message, channel):
    globals()[message['method']](message['data'])
def error(message):
    print("ERROR: " + str(message))
def connect(message):
    print("CONNECTED")
def reconnect(message):
    print("RECONNECTED")
def disconnect(message):
    print("DISCONNECTED")

G.setmode(G.BCM)

red_channel_pin = 18
green_channel_pin = 23
blue_channel_pin = 24

G.setup(red_channel_pin, G.OUT)
G.setup(green_channel_pin, G.OUT)
G.setup(blue_channel_pin, G.OUT)

pwm_red = G.PWM(red_channel_pin,500)
pwm_red.start(100)

pwm_green = G.PWM(green_channel_pin,500)
pwm_green.start(100)

pwm_blue = G.PWM(blue_channel_pin,500)
pwm_blue.start(100)

def set_rgb_values(data):
    pwm_red.ChangeDutyCycle(float(data['red']))
    pwm_green.ChangeDutyCycle(float(data['green']))
    pwm_blue.ChangeDutyCycle(float(data['blue']))

try:
    pubnub.subscribe(channels="rasprgb",callback=callback, error=error, connect=connect, reconnect=reconnect, disconnect=disconnect) 
except KeyboardInterrupt:
    print('Cleaning Up')
    G.cleanup()
    pubnub.unsubscribe(channel='rasprgb')

除了尝试关闭程序并清理 GPIO 引脚、取消订阅频道等之外,所有这些都有效。

过去我使用过while True: 循环并且它有效,但是由于我不想在这里循环执行某些操作,我只想打开一个连接并保持打开状态直到我终止它循环在这里没有意义

点击Ctrl + C 只会输出KeyboardInterrupt,但它似乎没有调用 except 块

我怎样才能让它能够终止和清理 GPIO 引脚?

更新

重构为使用signal 后,我现在替换了try...except(假设我已在文件顶部导入它们)

def sig_handler(signal,frame):
    print('Cleaning Up')
    G.cleanup()
    pubnub.unsubscribe(channel='rasprgb')
    sys.exit(0)

pubnub.subscribe(channels="rasprgb",callback=callback, error=error, connect=connect, reconnect=reconnect, disconnect=disconnect)
signal.signal(signal.SIGINT, sig_handler)

但是,按下ctrl + c 仍然不会关闭程序并运行清理代码

【问题讨论】:

  • 你试过 Ctrl-D 吗?
  • 没有,但它似乎 ctrl + d 只是关闭了外壳,当我再次运行脚本时,它会警告引脚已经在使用中,所以我真的需要进行清理

标签: python raspberry-pi pubnub keyboardinterrupt


【解决方案1】:

使用signal 模块,您可以创建一个全局中断处理程序:

import signal
import sys

def sig_handler(signal, frame):
    print('Cleaning Up')
    G.cleanup()
    pubnub.unsubscribe(channel='rasprgb')
    sys.exit(0)

signal.signal(signal.SIGINT, sig_handler)

现在,当您CTRL-C 时,您的清理代码将运行,程序将退出。我主要在我的 Pis 上使用 Perl,但我做同样的事情以确保在重新运行相同的应用程序或运行不同的应用程序之前重置所有引脚。

【讨论】:

  • 你没有把它放在 except 块中,是吗?
  • 不,signal.signal 是否进入异常块?
  • 不,不应该。在重构使用信号而不是 try/except 之后,会发生什么?什么都没有?
  • 用我的重构更新了主要问题
【解决方案2】:

您可以使用此功能的任何按键退出脚本。我也没有看到 while 循环有问题,但如果我真的需要另一种方法,我会使用这个:

import sys, os

def wait_key():
  ''' Wait for a key press on the console and return it. '''
  result = None

  import termios
  fd = sys.stdin.fileno()

  oldterm = termios.tcgetattr(fd)
  newattr = termios.tcgetattr(fd)
  newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
  termios.tcsetattr(fd, termios.TCSANOW, newattr)

  try:
      result = sys.stdin.read(1)
  except IOError:
      pass
  finally:
      termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)

  return result

print('Press any key to quit: ')
wait_key()

通过使用 curses 模块可以使用另一种类似的方法,如下所示:

import curses
stdscr = curses.initscr()
c = stdscr.getch()
print 'you entered', chr(c)
curses.endwin()

此外,如果您使用的是 Windows,则可以使用 msvcrt 模块:

import msvcrt
c = msvcrt.getch()
print 'you entered', c

【讨论】:

    猜你喜欢
    • 2023-01-19
    • 2019-12-23
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 1970-01-01
    • 2013-09-07
    相关资源
    最近更新 更多