Ответ 1
Указанный Ctrl+\
интерпретируется вашим программным обеспечением терминала, а привязка клавиш настраивается через stty
. Если у вас есть какой-либо способ настройки вашего программного обеспечения терминала, вы сможете использовать только несколько сигналов, которые уже встроены.
В зависимости от того, сколько функциональности вам нужно или насколько вы хотите ее принять, другой вариант - написать собственный простой "терминал выполнения процесса". Это будет script, который выполняет приложение для вас и помещает ваш терминал в необработанный режим, чтобы он мог обрабатывать нажатия клавиш, которые выполняют пользовательские действия.
Ниже приведен упрощенный пример, показывающий, что я имею в виду. Вы также можете сделать что-то подобное через curses или urwid если хотите.
Чтобы обрабатывать вывод процесса, вам нужно будет захватить stdout/stderr
и отобразить его на экране, используя ANSI escape-последовательности, если вы манипулируете терминалом вручную или используете виджет 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
script для вращения и печати полученных сигналов:
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'