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'
Я не уверен, если есть готовые способ определить новые сигналы и сопоставить их с событиями клавиатуры.
Если вам нужна такая гибкость, вам может потребоваться использовать поток интерфейса, который остается на переднем плане и прослушивает события клавиатуры. Затем он может общаться с другими потоками так, как вам нравится.