Python:内置键盘信号/中断

时间:2011-03-29 16:01:58

标签: python linux signals

我目前需要为程序提供多个键盘中断。使用信号类有一个简单的方法吗?我目前使用的是SIGINT / Ctrl+C,但我无法找到任何其他键盘映射。

拥有超过2个信号会很高兴。如何定义更多信号或者是否有更好的方法来捕获用户的中断"?

以下是当前代码的高级视图:

 def shutdown(signal, frame):
       if(signal==2): #sigint
          print 'do something'
       elif signal==XX:
          print 'do something else'
       # continued...

 signal.signal(signal.SIGINT, shutdown)
 signal.signal(signal.SOMEOTHERTYPE, shutdown)


 print 'start'
 t = Thread(target=run)
 t.setDaemon(True)
 t.start()

 print 'Done, press ctrl c, or ctrl ? '
 signal.pause()

3 个答案:

答案 0 :(得分:11)

已提及的Ctrl+\由终端软件解释,密钥绑定通过stty配置。除非你有一些自定义终端软件的方法,否则你只能使用已经内置的少量信号。

根据您需要的功能或您想要的功能,另一个选择是编写您自己的简单“流程执行终端”。这将是一个为您执行应用程序并将终端置于原始模式的脚本,以便它可以处理执行自定义操作的击键。

下面是一个过于简单的示例,显示了我的意思。如果您愿意,也可以通过cursesurwid执行类似操作。

要处理流程输出,您需要捕获stdout/stderr并将其显示在屏幕上,如果您手动操作终端,则使用ANSI escape sequences或使用urwid小部件显示在滚动窗口输出等。同样的想法也会扩展到其他GUI系统(wx,tkinter等),但提到了终端控制。

这是实现基本原始终端解释器的term.py

import os, signal, subprocess, sys, tty, termios

sigmap = {
    '\x15': signal.SIGUSR1,     # ctrl-u
    '\x1c': signal.SIGQUIT,     # ctrl-\
    '\x08': signal.SIGHUP,      # ctrl-h
    '\x09': signal.SIGINT,      # ctrl-i
    }
# setup tty
fd = sys.stdin.fileno()
old_tc = termios.tcgetattr(fd)
tty.setraw(fd)
# spawn command as a child proc
cmd = sys.argv[1:]
proc = subprocess.Popen(cmd)
while 1:
    try:
        ch = sys.stdin.read(1)
        # example of ansi escape to move cursor down and to column 0
        print '\033[1Eyou entered', repr(ch)
        if ch == 'q':
            break
        signum = sigmap.get(ch)
        if signum:
            os.kill(proc.pid, signum)
    finally:
        pass
termios.tcsetattr(fd, termios.TCSANOW, old_tc)
sys.exit()

这是一个简单的target.py脚本,用于旋转和打印它收到的信号:

import signal, sys, time

def handler(num, _):
    print 'got:', sigmap.get(num, '<other>')
    if num == signal.SIGINT:
        sys.exit(1)
    return 1

signames = ['SIGINT','SIGHUP','SIGQUIT','SIGUSR1']
sigmap = dict((getattr(signal, k), k) for k in signames)
for name in signames:
    signal.signal(getattr(signal, name), handler)
while 1:
    time.sleep(1)

用法示例:

% python term.py python target.py
you entered 'h'
you entered 'i'
you entered '\x1c'
                  got: SIGQUIT
you entered '\x15'
                  got: SIGUSR1
you entered '\x08'
                  got: SIGHUP
you entered '\t'
                got: SIGINT
you entered 'q'

答案 1 :(得分:5)

在Linux系统上,Ctrl + \将生成signal.SIGQUIT信号。

答案 2 :(得分:0)

我不确定是否有一种预先固定的方式来定义新信号并将它们映射到键盘事件。

如果您需要这种灵活性,则可能必须使用保留在前台的接口线程并侦听键盘事件。然后它可以以任何你喜欢的方式与其他线程通信。