Ошибка ввода после уничтожения менее (1) подпроцесса - PullRequest
5 голосов
/ 22 декабря 2011

Я пишу программу, которая отображает текст на терминале, используя Unix less (1). Вот соответствующая часть:

less = subprocess.Popen(['less -F -'], stdin=subprocess.PIPE, 
            stdout=sys.stdout, shell=True)
try:
    less.stdin.write(rfc_text)
    less.stdin.flush()
    less.stdin = sys.stdin
    less.wait()
except IOError:
    less.terminate()
    return errno.EPIPE
except KeyboardInterrupt:
    less.terminate()
    return 0

В ожидании завершения, я слушаю исключение KeyboardInterrupt. Если я поймаю его, я убью меньше с помощью сигнала SIGTERM и выйду из своей программы.

Теперь, когда это происходит, я возвращаюсь к моей подсказке оболочки, но оболочка больше не повторяет то, что я пишу, и мне приходится делать сброс (1), чтобы она снова заработала.

Есть какие-нибудь идеи о том, как заставить меньше умирать, не взяв с собой мой stdin в могилу? Полный источник доступен на https://github.com/jforberg/rfc/blob/master/rfc.py

РЕДАКТИРОВАТЬ: После некоторых экспериментов я обнаружил, что и less (1), и man (1) по умолчанию игнорируют удар control-C. Поэтому простое игнорирование может быть приемлемым вариантом. Я не уверен, что думаю, что это правильный способ сделать это, поэтому, если у кого-то есть предложения, я все еще очень заинтересован.

Ответы [ 3 ]

1 голос
/ 22 декабря 2011

В основном есть две опции:

  1. Меньше, программы man и связанные с ними программы не завершаются при control-C, они просто прерывают любую операцию, которую они выполняют в данный момент.Так что просто игнорировать нажатие клавиши, кажется, вариант.Это сохранило бы полезную особенность, заключающуюся в том, что длительные операции, такие как долгий поиск, могут быть прерваны без остановки программы.Также желательно, чтобы программа функционировала подобно аналогичным программам (в данном случае, Unix man).

  2. Less принимает опцию -K, которая заставит ее завершиться после control-C, простокак и большинство неинтерактивных команд.

1 голос
/ 22 декабря 2011

Самый простой способ - попросить пользователя правильно выйти из less (нажав q):

#!/usr/bin/env python
from subprocess import PIPE, Popen

p = Popen(['less'], stdin=PIPE)
try:
    p.communicate(''.join("%d\n" % i for i in range(1000)))
except KeyboardInterrupt:
    print("Press `q` to exit.")
    p.wait()
0 голосов
/ 24 января 2013

Ах, ах!Решение JF Sebastian хорошо, но оно работает не во всех случаях.В моем приложении я хочу использовать "less", как "tail -f", что делается с "less + F -S logfilename".Пользователь должен нажать CTRL + C, чтобы войти в нормальный режим, и нажать Q, чтобы выйти.

Чтобы эта процедура прошла без проблем, я предложил следующее 6-строчное решение (на основена код JF Себастьян):

logpath = os.path.join(cwd, "filename.log")
less = Popen(["less","+F","-S", logpath])
retcode = None
while retcode is None:
    try: retcode = less.wait()
    except KeyboardInterrupt: pass

Я думаю, что это решает оригинал.Если вы хотите ввести что-то меньшее, вам, возможно, придется настроить используемый метод Popen: либо wait(), либо communicate(input).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...