Python: встроенный сигнал/прерывания клавиатуры

В настоящее время мне нужно предоставить несколько прерываний клавиатуры для программы. Есть ли простой способ сделать это с помощью класса signal? В настоящее время я использую 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 ответов


The Ctrl+\ Это было упомянуто интерпретируется вашим программным обеспечением терминала, и привязка ключа настраивается через stty. Если у вас нет способа настроить программное обеспечение терминала, вы сможете использовать только те несколько сигналов, которые уже встроены.

в зависимости от того, сколько функциональности вам нужно или как далеко вы хотите взять его, другой вариант-написать свой собственный простой "терминал выполнения процесса". Это будет скрипт, который запускает приложение для вас и переводит терминал в режим raw, чтобы он мог обрабатывать нажатия клавиш, выполняющие пользовательские действия.

ниже приведен упрощенный пример, показывающий, что я имею в виду. Вы также можете сделать что-то подобное через проклятие или urwid если вам нравится.

для обработки вывода процесса вам нужно будет захватить stdout/stderr и отображать их на экране, используя ANSI escape-последовательности если вы манипулируете терминалом вручную или используете виджет urwid для отображения результата в окне с прокруткой и т. д. Та же идея будет распространяться и на другие системы GUI (wx, tkinter и т. д.), Но было упомянуто терминальное управление.

здесь term.py который реализует базовый интерпретатор raw-терминала:

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 '3[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'

в системах Linux Ctrl+\ будет генерировать сигнал.Сигнал SIGQUIT.


Я не уверен, если есть готовые способ определить новые сигналы и сопоставить их с событиями клавиатуры.

Если вам нужна такая гибкость, вам может потребоваться использовать поток интерфейса, который остается на переднем плане и прослушивает события клавиатуры. Затем он может общаться с другими потоками так, как вам нравится.