Как вы читаете со стандартного ввода в 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
предназначен для чтения в серии файлов.