Как читать строки за строкой из stdin в python

Всем известно, как считать символы из STDIN в C. Однако, когда я пытался это сделать в python3, я считаю, что это головоломка. (Counter.py)

import sys
chrCounter = 0

for line in sys.stdin.readline():
    chrCounter += len(line)

print(chrCounter)

Затем я пытаюсь проверить программу на

python3 counter.py < counter.py

Ответ - это только длина первой строки "import sys". Фактически, программа ТОЛЬКО считывает первую строку со стандартного ввода и отбрасывает остальную часть.

Это будет работа, если я заменю sys.stdin.readline на sys.stdin.read()

import sys
print(len(sys.stdin.read()))

Однако, очевидно, что программа НЕ подходит для большого ввода. Пожалуйста, дайте мне элегантное решение. Спасибо!

Ответ 1

Это проще:

for line in sys.stdin:
    chrCounter += len(line)

Файл-подобный объект sys.stdin автоматически повторяется по строкам; если вы вызываете .readline() на нем, вы читаете только первую строку (и повторяете этот символ по-символу); если вы вызываете read(), то вы будете считывать весь ввод в одну строку и перебирать этот символ-by.character.

Ответ 2

Если бы мне просто нужен счетчик символов, я бы читал в блоках за раз, а не по строкам за раз:

# 4096 chosen arbitrarily. Pick any other number you want to use.
print(sum(iter(lambda:len(sys.stdin.read(4096)), 0)))

Ответ 3

Ответ от Тима Пицкера - это ИМХО правильный. Есть два аналогичных способа сделать это. Использование:

for line in sys.stdin:

и

for line in sys.stdin.readlines():

Второй вариант ближе к вашему исходному коду. Различие между этими двумя вариантами становится ясным, используя, например, следующую модификацию тела for-loop и использование клавиатуры для ввода:

for line in sys.stdin.readlines():
    line_len = len(line)
    print('Last line was', line_len, 'chars long.')
    chrCounter += len(line)

Если вы используете первый вариант (for line in sys.stdin:), тогда строки обрабатываются сразу после нажатия кнопки ввода.

Если вы используете второй вариант (for line in sys.stdin.readlines():), тогда весь файл сначала считывается, разбивается на строки и только затем обрабатывается.