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

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

Ответы

Ответ 1

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

import fileinput

for line in fileinput.input():
    pass

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

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

Ответ 2

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

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

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

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

Вы, вероятно, найдете эту статью в Википедии о вводе-выводе в Python также полезной ссылкой.

Ответ 3

import sys

for line in sys.stdin:
    print(line)

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

Ответ 4

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

Например,

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

или

name = input("Enter your name: ")   # Python 3

Ответ 5

Здесь из Learning 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.

Ответ 6

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

for line in sys.stdin:
  print line

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

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

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

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

    if not line:
        break

    print line

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

Ответ 7

  Как вы читаете со стандартного ввода в 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 - вероятно, ваш лучший выбор для игры в гольф. В Python 2 это io.open.
  • open('/dev/stdin').read() - аналогично open(0), работает на Python 2 и 3, но не на Windows (или даже Cygwin).
  • fileinput.input() - возвращает итератор над строками во всех файлах, перечисленных в sys.argv[1:], или stdin, если не указан. Используйте как ''.join(fileinput.input()).

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

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

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

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

Мы видим, что sys.stdin находится в текстовом режиме по умолчанию:

>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>

пример файла

Скажем, у вас есть файл, 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' для записи в stdout).

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

$ 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 (после Enter), чтобы отправить символ конца файла процессу. Кроме того, в этом ответе предлагается print(line) - который добавляет '\n' к концу - используйте вместо него print(line, end='') (если в Python 2 вам понадобится from __future__ import print_function).

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

Ответ 8

Это приведет к стандартному входу стандартного вывода:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()

Ответ 9

Основываясь на всех anwers с помощью 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 script будет вести себя как многие программы GNU/Unix, такие как cat, grep и sed.

Ответ 10

argparse - это простое решение

Пример совместим с обеими версиями Python 2 и 3:

#!/usr/bin/python

import argparse
import sys

parser = argparse.ArgumentParser()

parser.add_argument('infile',
                    default=sys.stdin,
                    type=argparse.FileType('r'),
                    nargs='?')

args = parser.parse_args()

data = args.infile.read()

Вы можете запустить этот скрипт разными способами:

1. Использование стандартного stdin

echo 'foo bar' | ./above-script.py

или короче, заменив echo на следующую строку:

./above-script.py <<< 'foo bar'

2. Использование аргумента имени файла

echo 'foo bar' > my-file.data
./above-script.py my-file.data

3. Использование stdin через специальное имя файла -

echo 'foo bar' | ./above-script.py -

Ответ 11

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

import sys
input_str = sys.stdin.read()
print input_str.split()

Ответ 12

Попробуйте следующее:

import sys

print sys.stdin.read().upper()

и проверьте его с помощью:

$ echo "Hello World" | python myFile.py

Ответ 13

Вы можете читать из stdin, а затем хранить входы в "данные" следующим образом:

data = ""
for line in sys.stdin:
    data += line

Ответ 14

Считайте из sys.stdin, но чтобы читать двоичные данные в Windows, вам нужно быть особенно осторожным, потому что sys.stdin открывается в текстовом режиме, и это приведет к повреждению \r\n, заменяющему их с \n.

Решение состоит в том, чтобы установить режим в двоичный, если обнаружен Windows + Python 2, а на Python 3 используйте sys.stdin.buffer.

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

Ответ 15

Я очень удивлен, что никто пока не упоминал об этом хаке:

python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"

совместим с python2 и python3

Ответ 16

Проблема с решением

import sys

for line in sys.stdin:
    print(line)

заключается в том, что если вы не передадите какие-либо данные в stdin, он будет блокироваться навсегда. Вот почему я люблю этот ответ: сначала проверьте, есть ли какие-то данные по stdin, а затем прочитайте его. Это то, что я закончил:

import sys
import select

# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
    help_file_fragment = sys.stdin.read()
else:
    print("No data passed to stdin", file=sys.stderr)
    sys.exit(2)

Ответ 17

У меня возникли некоторые проблемы при работе с ним для чтения через сокеты, подключенные к нему. Когда сокет закрылся, он начал возвращать пустую строку в активном цикле. Так что это мое решение для меня (которое я тестировал только в Linux, но надеюсь, что он работает во всех других системах)

import sys, os
sep=os.linesep

while sep == os.linesep:
    data = sys.stdin.readline()               
    sep = data[-len(os.linesep):]
    print '> "%s"' % data.strip()

Итак, если вы начнете прослушивать сокет, он будет работать правильно (например, в bash):

while :; do nc -l 12345 | python test.py ; done

И вы можете вызвать его с помощью telnet или просто указать браузер на localhost: 12345

Ответ 18

Относительно этого:

for line in sys.stdin:

Я просто попробовал это на python 2.7 (после какого-то другого предложения) для очень большого файла, и я не рекомендую его именно по причинам, упомянутым выше (ничего не происходит в течение длительного времени).

В итоге у меня появилось несколько более питоническое решение (и оно работает с большими файлами):

with open(sys.argv[1], 'r') as f:
    for line in f:

Затем я могу запустить script локально как:

python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work

Ответ 19

n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()

Ответ 20

Один из вариантов - использовать функцию ввода, как показано ниже. Существует также метод raw_input, если вы не уверены в типе данных.

#!/usr/bin/env python

number = input("Please enter a number : ")
print("Entered number is %d" % number)

Запуск программы:

python test1.py

Please enter a number : 55
Entered number is 55

Ссылка: http://www.python-course.eu/input.php

Ответ 21

Существует os.read(0, x) который читает xbytes из 0, что представляет собой стандартный ввод. Это небуферизованное чтение, более низкий уровень, чем sys.stdin.read()

Ответ 22

Для Python 3 это будет:

# Filename e.g. cat.py
import sys

for line in sys.stdin:
    print(line, end="")

Это в основном простая форма cat (1), так как она не добавляет символ новой строки после каждой строки. Вы можете использовать это (после того, как Вы отметили исполняемый файл, используя chmod +x cat.py например:

echo Hello | ./cat.py

Ответ 23

При использовании команды -c в качестве хитрого способа вместо чтения стандартного stdin (и в некоторых случаях более гибкого) вы можете также передать команду сценария оболочки в команду python, поместив команду sell в кавычки в скобках, начинающихся с знак $.

например

python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"

Это будет подсчитывать количество строк из файла истории goldendict.