Не удается запустить интерактивную программу при конвейерной обработке скрипта в Python - PullRequest
2 голосов
/ 13 мая 2011

У меня есть сценарий Python, который должен вызвать определенный $EDITOR или $VISUAL.Когда скрипт Python вызывается один, я могу запустить $EDITOR без проблем, но в тот момент, когда я передаю что-то скрипту Python, $EDITOR не может запуститься.Прямо сейчас я использую nano, который показывает

Получено SIGHUP или SIGTERM

каждый раз.Кажется, это та же самая проблема , описанная здесь .

sinister:Programming [1313]$ echo "import os;os.system('nano')" > "sample.py" 
sinister:Programming [1314]$ python sample.py
# nano is successfully launched here.
sinister:Programming [1315]$ echo "It dies here." | python sample.py 
Received SIGHUP or SIGTERM

Buffer written to nano.save.1

РЕДАКТИРОВАТЬ: Уточнение;Внутри программы я не обожаю редактор.Код выглядит следующим образом:

editorprocess = subprocess.Popen([editor or "vi", temppath])
editorreturncode = os.waitpid(editorprocess.pid, 0)[1]

Ответы [ 2 ]

4 голосов
/ 13 мая 2011

Когда вы передаете что-то процессу, канал подключается к стандартному входу этого процесса.Это означает, что ваш терминал ввода не будет подключен к редактору.Большинство редакторов также проверяют, является ли их стандартный ввод терминалом ( isatty ), а не каналом;и если это не терминал, они откажутся начинать.В случае nano это, по-видимому, приводит к его завершению с сообщением, которое вы включили:

% echo | nano
Received SIGHUP or SIGTERM

Вам нужно будет предоставить входные данные для вашего сценария Python другим способом, например, черезфайл, если вы хотите иметь возможность передавать его стандартный ввод в редактор на основе терминала.

Теперь вы уточнили свой вопрос, что вы не хотите, чтобы процесс Python stdin был присоединен к редактору.Вы можете изменить свой код следующим образом:

editorprocess = subprocess.Popen([editor or "vi", temppath],
                                 stdin=open('/dev/tty', 'r'))
2 голосов
/ 13 мая 2011

Здесь обрабатывается конкретный случай find -type f | vidir -:

foreach my $item (@ARGV) {
    if ($item eq "-") {
        push @dir, map { chomp; $_ } <STDIN>;
        close STDIN;
        open(STDIN, "/dev/tty") || die "reopen: $!\n";
    }

Вы также можете воссоздать это поведение в Python:

#!/usr/bin/python

import os
import sys

sys.stdin.close()
o = os.open("/dev/tty", os.O_RDONLY)
os.dup2(o, 0)
os.system('vim')

Конечно, это закрывает стандартный дескриптор входного файла, поэтому, если вы собираетесь читать его снова после запуска редактора, вам, вероятно, следует продублировать его дескриптор файла перед закрытием.

...