Как вы читаете со стандартного ввода? - PullRequest
1317 голосов
/ 20 сентября 2009

Я пытаюсь выполнить некоторые задачи code golf , но все они требуют ввода данных из stdin. Как мне получить это в Python?

Ответы [ 21 ]

879 голосов
/ 21 сентября 2009

Вы можете использовать модуль fileinput:

import fileinput

for line in fileinput.input():
    pass

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

Примечание: line будет содержать завершающий перевод строки; чтобы удалить это используйте line.rstrip()

664 голосов
/ 20 сентября 2009

Есть несколько способов сделать это.

  • sys.stdin - это файлоподобный объект, для которого вы можете вызывать функции read или readlines, если вы хотите прочитать все или вы хотите прочитать все и разбить его на новая строка автоматически. (Вам нужно import sys, чтобы это работало.)

  • Если вы хотите запросить пользователя для ввода, вы можете использовать raw_input в Python 2.X и просто input в Python 3.

  • Если вы на самом деле просто хотите прочитать параметры командной строки, вы можете получить к ним доступ через список sys.argv .

Возможно, вы найдете эту статью Wikibook о вводе / выводе в Python также полезной ссылкой.

382 голосов
/ 20 июля 2010
import sys

for line in sys.stdin:
    print line

Обратите внимание, что в конце будет добавлен символ новой строки. Чтобы удалить символ новой строки в конце, используйте line.rstrip (), как сказал @brittohalloran.

208 голосов
/ 03 марта 2011

Python также имеет встроенные функции input() и raw_input(). См. Документацию по Python в разделе Встроенные функции .

Например,

name = raw_input("Enter your name: ")   # Python 2.x

или

name = input("Enter your name: ")   # Python 3
177 голосов
/ 20 сентября 2009

Вот из Изучение Python :

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."

В Unix вы можете проверить это, выполнив что-то вроде:

% cat countlines.py | python countlines.py 
Counted 3 lines.

В Windows или DOS вы должны сделать:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.
94 голосов
/ 30 сентября 2011

Ответ, предложенный другими:

for line in sys.stdin:
  print line

очень прост и питоничен, но следует отметить, что сценарий будет ждать до EOF, прежде чем начать итерацию в строках ввода.

Это означает, что tail -f error_log | myscript.py не будет обрабатывать строки, как ожидалось.

Правильный сценарий для такого варианта использования будет:

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

UPDATE
Из комментариев выяснилось, что только в python 2 может быть задействована буферизация, так что вы в конечном итоге ожидаете заполнения буфера или EOF до вызова вызова.

79 голосов
/ 30 июля 2016

Как вы читаете со стандартного ввода в Python?

Я пытаюсь решить некоторые проблемы с гольф-кодом, но все они требуют ввода от stdin. Как мне получить это в Python?

Вы можете использовать:

  • sys.stdin - Файловый объект - вызовите sys.stdin.read(), чтобы прочитать все.
  • input(prompt) - передайте ему необязательное приглашение для вывода, оно читает от стандартного ввода до первой новой строки, которую удаляет. Вам придется делать это несколько раз, чтобы получить больше строк, в конце ввода это вызывает EOFError. (Вероятно, не подходит для игры в гольф.) В Python 2 это rawinput(prompt).
  • open(0).read() - В Python 3 open принимает файловые дескрипторы (целые числа, представляющие ресурсы ввода-вывода операционной системы), а 0 - дескриптор stdin. Он возвращает файл-подобный объект, такой как sys.stdin - вероятно, ваш лучший выбор для игры в гольф.
  • open('/dev/stdin').read() - аналогично open(0), работает на Python 2 и 3, но не на Windows (или даже Cygwin).
  • fileinput.input() - возвращает итератор по строкам во всех файлах, перечисленных в sys.argv[1:], или stdin, если не указан. Используйте как ''.join(fileinput.input()).

И sys, и fileinput должны быть импортированы соответственно.

Quick sys.stdin примеры, совместимые с Python 2 и 3, Windows, Unix

Вам просто нужно read из sys.stdin, например, если вы передаете данные в stdin:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

пример файла

Скажем, у вас есть файл, inputs.txt, мы можем принять этот файл и записать его обратно:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

Более длинный ответ

Вот полная, легко тиражируемая демонстрация с использованием двух методов: встроенной функции, input (используйте raw_input в Python 2) и sys.stdin. Данные не изменены, поэтому обработка не выполняется.

Для начала давайте создадим файл для входных данных:

$ python -c "print('foo\nbar\nbaz')" > inputs.txt

И используя код, который мы уже видели, мы можем проверить, что создали файл:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt 
foo
bar
baz

Вот справка по sys.stdin.read из Python 3:

read(size=-1, /) method of _io.TextIOWrapper instance
    Read at most n characters from stream.

    Read from underlying buffer until we have n characters or we hit EOF.
    If n is negative or omitted, read until EOF.

Встроенная функция, input (raw_input в Python 2)

Встроенная функция input читает от стандартного ввода до новой строки, которая удаляется (дополняет print, который добавляет новую строку по умолчанию.) Это происходит до тех пор, пока не получит EOF (Конец файла), после чего это поднимает EOFError.

Таким образом, вот как вы можете использовать input в Python 3 (или raw_input в Python 2) для чтения из stdin - поэтому мы создаем модуль Python, который мы называем stdindemo.py:

$ python -c "print('try:\n    while True:\n        print(input())\nexcept EOFError:\n    pass')" > stdindemo.py 

И давайте распечатаем его обратно, чтобы убедиться, что это так, как мы ожидаем:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

Опять же, input читает до новой строки и по существу удаляет его из строки. print добавляет новую строку. Поэтому, пока они оба изменяют ввод, их модификации отменяются. (Так что они по сути являются дополнением друг друга.)

И когда input получает символ конца файла, он вызывает EOFError, которую мы игнорируем, а затем выходим из программы.

А в Linux / Unix мы можем передать из cat:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

Или мы можем просто перенаправить файл из стандартного ввода:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

Мы также можем выполнить модуль как скрипт:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

Вот справка по встроенному input из Python 3:

input(prompt=None, /)
    Read a string from standard input.  The trailing newline is stripped.

    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.

    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.

sys.stdin

Здесь мы создаем демонстрационный скрипт, используя sys.stdin. Эффективный способ перебора файловоподобного объекта заключается в использовании файловоподобного объекта в качестве итератора. Дополнительный метод записи в стандартный вывод с этого входа - просто использовать sys.stdout.write:

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

Распечатайте его обратно, чтобы убедиться, что оно выглядит правильно:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

И перенаправление входных данных в файл:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

Гольф в команде:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz

Файловые дескрипторы для игры в гольф

Поскольку файловые дескрипторы для stdin и stdout равны 0 и 1 соответственно, мы также можем передать их в open в Python 3 (не 2, и обратите внимание, что нам все еще нужен 'w' для записи в стандартный вывод).

Если это работает в вашей системе, оно сбрит больше символов.

$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo

Python 2 io.open также делает это, но импорт занимает намного больше места:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

Обращаясь к другим комментариям и ответам

Один комментарий предлагает ''.join(sys.stdin), но на самом деле это больше, чем sys.stdin.read () - плюс Python должен создать дополнительный список в памяти (вот как str.join работает, когда нет списка) - для контраста:

''.join(sys.stdin)
sys.stdin.read()

Верхний ответ предполагает:

import fileinput

for line in fileinput.input():
    pass

Но, поскольку sys.stdin реализует файловый API, включая протокол итератора, он такой же, как и этот:

import sys

for line in sys.stdin:
    pass

Другой ответ предлагает . Просто помните, что если вы делаете это в интерпретаторе, вам нужно будет выполнить Ctrl - d , если вы используете Linux или Mac, или Ctrl - z в Windows (после Введите ), чтобы отправить символ конца файла процессу. Кроме того, этот ответ предполагает print(line) - что добавляет '\n' к концу - вместо этого используйте print(line, end='') (если в Python 2 вам понадобится from __future__ import print_function).

Реальный вариант использования fileinput предназначен для чтения в серии файлов.

37 голосов
/ 09 августа 2012

Это будет выводить стандартный ввод на стандартный вывод:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()
30 голосов
/ 29 июля 2013

Опираясь на все ответы, используя sys.stdin, вы также можете сделать что-то вроде следующего, чтобы прочитать из файла аргументов, если существует хотя бы один аргумент, и в противном случае вернуться к stdin:

import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin    
for line in f:
#     Do your stuff

и используйте его как

$ python do-my-stuff.py infile.txt

или

$ cat infile.txt | python do-my-stuff.py

или даже

$ python do-my-stuff.py < infile.txt

Это приведет к тому, что ваш скрипт на Python будет вести себя подобно многим программам GNU / Unix, таким как cat, grep и sed.

14 голосов
/ 25 января 2016

Вам поможет следующий фрагмент кода (он будет считывать все блокировки стандартного ввода в EOF в одну строку):

import sys
input_str = sys.stdin.read()
print input_str.split()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...