Читать Python stdin из канала, не блокируя при пустом вводе - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь прочитать stdin в скрипте Python при получении из канала.

Я использовал следующие строки:

for line in sys.stdin:
    print line

И запустил скрипт: echo "test" | script.py

Пока все отлично работает.Однако, если я не использую канал, программа придерживается команды for.Это означает, что вызов: ./script.py заставит скрипт не работать.Как я могу это исправить?

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Ваш скрипт работает, просто кажется, что ваши ожидания не верны.

script.py (с учетом Python 3, который я установил):

import sys
for line in sys.stdin:
    print(line)

$ python script.py
abcd
abcd

xyz
xyz

Где первые вхождения "abcd" и "xyz" были моими входными данными изклавиатура и вторые были выходами программы.Я прекратил выполнение в этот момент с помощью ctrl-d.

Проблема в том, что чтение из stdin без ввода из канала не дает того, что вы ожидаете.Когда вы просто запускаете скрипт (без ввода по трубопроводу), он просто сидит и ждет, когда вы что-то введете с клавиатуры.Возможно, вы захотите изучить raw_input для получения ввода с клавиатуры.

Обновление:

После получения дополнительных разъяснений в комментариях о том, что вы хотите,следующий скрипт может дать вам желаемые результаты:

import sys
if not sys.stdin.isatty():
    for line in sys.stdin:
        print(line)

print("More stuff!")
0 голосов
/ 29 ноября 2018

Вы можете проверить, была ли программа передана по трубопроводу, вызвав isatty в дескрипторе файла, полученном из sys.stdin.

Примерно так:

import os
import sys

if not os.isatty(sys.stdin.fileno()):
    print (sys.stdin.readlines())
else:
    print ("Skip, so it doesn't hang")

Пример 1:

 echo "test" | python ./script.py
 ['test\n']

Пример 2:

 python ./script.py 
 Skip, so it doesn't hang
0 голосов
/ 29 ноября 2018

Редактировать: вы, очевидно, даже не хотите, чтобы он читал строки в этом случае или обрабатывал KeyboardInterrupt, поэтому вам нужно проверить наличие пустых stdin.Проверьте, являетесь ли вы терминалом, и пройдите, как показано в отредактированном примере.


sys.stdin имеет файловую форму.Попробуйте:

if not sys.stdin.isatty():
    data = sys.stdin.readlines()
    # Do something with data

Если вы запустите это без stdin, я не думаю, что оно зависнет, как раньше, потому что sys.stdin будет пустым.Затем функция должна продолжиться.

...