Каналы и подсказки в скриптах Python CLI - PullRequest
5 голосов
/ 11 июня 2011

Можно ли комбинировать ввод по каналу и запросы TTY в скриптах Python CLI?Например, запустив это:

import sys

piped_text = None

if not sys.stdin.isatty():
    piped_text = sys.stdin.read()

user_in = raw_input('Enter something: ')

if piped_text:
    sys.stdout.write(piped_text)

sys.stdout.write(user_in + '\n')  

Создает следующий вывод:

~: python mrprompt.py
Enter something: something
something
~: echo foo | python mrprompt.py
Enter something: Traceback (most recent call last):
  File "mrprompt.py", line 9, in <module>
    user_in = raw_input('Enter something: ')
EOFError: EOF when reading a line

Когда искомый вывод такой:Иными словами, может ли подоболочка знать tty своей родительской оболочки?Возможно ли в Python взаимодействовать с tty родительской оболочки?Я использую bash внутри GNU Screen (поэтому чтение переменной окружения 'SSH_TTY' не является приемлемым вариантом).

Ответы [ 3 ]

6 голосов
/ 11 июня 2011

Это работает, более или менее:

#!/usr/bin/python

import sys

saved_stdin = sys.stdin
sys.stdin = open('/dev/tty', 'r')
result = raw_input('Enter something: ')
sys.stdout.write('Got: ' + result + '\n')
sys.stdin = saved_stdin
result2 = sys.stdin.read()
sys.stdout.write('Also got: ' + result2)

Сохранить как foo.py и попробовать echo goodbye | ./foo.py

Конечно, /dev/tty существует только в Unix. И если вы запустите его в процессе без управляющего терминала, open(), вероятно, потерпит неудачу ...

5 голосов
/ 11 июня 2011

Вы можете определить, идет ли ваш stdin из трубы, как вы с sys.stdin.isatty.Вы получаете EOF, потому что вы читаете все входные данные с помощью stdin.read(), а затем пытаетесь прочитать еще немного с помощью команды raw_input().

Что вы можетене делать как вход трубы и сделать интерактивный ввод.Если вы вводите данные, нет другого stdin для raw_input, с которым можно работать.Единственный stdin - это тот, который приходит из файла.

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

--input=file.txt

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

1 голос
/ 11 июня 2011

В одной и той же программе можно принимать как ввод по каналу, так и ввод пользователя.

Самый простой способ справиться с этим - с помощью модуля subprocess.Вы выполняете программу из вашей программы Python.Аргументы для него позволяют вам устанавливать каналы и / или из программы, которую вы выполняете.

Это просто.Это стандартно.Это работает хорошо.

То же самое верно для принятия файла через аргументы программы.Это просто.Это стандартно.Это работает хорошо.Как дополнительное преимущество, в Windows CMD.EXE / COMMAND.COM автоматически использует временные файлы для каналов.Вы не получаете никакой выгоды от того, что делаете что-то более сложное из-за того, что DOS / Windows не поддерживают настоящие каналы.

Я знаю, что клиентский код командной строки mysql принимает пароль от пользователя перед обработкой вводимого по трубопроводу ввода.Решение Linux (и, вероятно, Mac OS X) для этого, вероятно, похоже на то, что опубликовал Nemo.Если это действительно то поведение, которое вам действительно нужно, и вы не заботитесь о Windows, это решение для использования.(Для Windows вам нужно использовать что-то вроде пакета wconio. - http://newcenturycomputers.net/projects/wconio.html)

- это , который может иметь пользовательский ввод и принимать конвейерный вывод, идущий для другая программа. Существует три стандартных дескриптора файла: stdin, stdout и stderr. Вы можете писать в stderr, даже когда stdout перенаправляется в файл.

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