You can wrap stdin to strip the newlines; if you can strip all trailing whitespace (usually okay), then it's just:
for name in map(str.rstrip, sys.stdin):
...
You're on Py3, so that works as is; if you're on Py2, you'll need to add an import, from future_builtins import map, so you get a lazy, generator based map (that yields the lines as they're requested, rather than slurping stdin until it ends, then returning a list of all the lines).
If you need to limit to newlines, a generator expression can do it:
for name in (line.rstrip("\r\n") for line in sys.stdin):
...
or with an import to allow map to push work to C layer for (slightly) faster code (a matter of 30-some nanoseconds per line faster than the genexpr, but still 40 ns per line slower than the argumentless option at the top of this answer):
from operator import methodcaller
for name in map(methodcaller('rstrip', '\r\n'), sys.stdin):
...
Like the first solution, on Py2, make sure to get the map from future_builtins.
You can wrap stdin to strip the newlines; if you can strip all trailing whitespace (usually okay), then it's just:
for name in map(str.rstrip, sys.stdin):
...
You're on Py3, so that works as is; if you're on Py2, you'll need to add an import, from future_builtins import map, so you get a lazy, generator based map (that yields the lines as they're requested, rather than slurping stdin until it ends, then returning a list of all the lines).
If you need to limit to newlines, a generator expression can do it:
for name in (line.rstrip("\r\n") for line in sys.stdin):
...
or with an import to allow map to push work to C layer for (slightly) faster code (a matter of 30-some nanoseconds per line faster than the genexpr, but still 40 ns per line slower than the argumentless option at the top of this answer):
from operator import methodcaller
for name in map(methodcaller('rstrip', '\r\n'), sys.stdin):
...
Like the first solution, on Py2, make sure to get the map from future_builtins.
I wouldn't recommend you this, but you can create a generator to be used in a for loop to iterate through input line by line:
def getlines():
while True:
yield input()
for name in getlines():
print(name)
## Remember to break out of the loop at some point
The following should just work.
import sys
for line in sys.stdin:
# whatever
Rationale:
The code will iterate over lines in stdin as they come in. If the stream is still open, but there isn't a complete line then the loop will hang until either a newline character is encountered (and the whole line returned) or the stream is closed (and the whatever is left in the buffer is returned).
Once the stream has been closed, no more data can be written to or read from stdin. Period.
The reason that your code was overloading your cpu is that once the stdin has been closed any subsequent attempts to iterate over stdin will return immediately without doing anything. In essence your code was equivalent to the following.
for line in sys.stdin:
# do something
while 1:
pass # infinite loop, very CPU intensive
Maybe it would be useful if you posted how you were writing data to stdin.
EDIT:
Python will (for the purposes of for loops, iterators and readlines() consider a stream closed when it encounters an EOF character. You can ask python to read more data after this, but you cannot use any of the previous methods. The python man page recommends using
import sys
while True:
line = sys.stdin.readline()
# do something with line
When an EOF character is encountered readline will return an empty string. The next call to readline will function as normal if the stream is still open. You can test this out yourself by running the command in a terminal. Pressing ctrl+D will cause a terminal to write the EOF character to stdin. This will cause the first program in this post to terminate, but the last program will continue to read data until the stream is actually closed. The last program should not 100% your CPU as readline will wait until there is data to return rather than returning an empty string.
I only have the problem of a busy loop when I try readline from an actual file. But when reading from stdin, readline happily blocks.
This actually works flawlessly (i.e. no runnaway CPU) - when you call the script from the shell, like so:
tail -f input-file | yourscript.py
Obviously, that is not ideal - since you then have to write all relevant stdout to that file -
but it works without a lot of overhead!
Namely because of using readline() - I think:
while 1:
line = sys.stdin.readline()
It will actually stop and wait at that line until it gets more input.
Hope this helps someone!
python - Loop on sys.stdin - Stack Overflow
How do I process a multiple line input from "for line in sys.stdin:"?
Python sys.stdin.read(1) in a while(True) loop consistently executes 1 time getting input and multiple times not getting input - Stack Overflow
python - reading from stdin, while consuming no more memory than needed - Stack Overflow
I recently took a coding assessment where I was tasked to compute the square of the input which is relatively easy. The issue was that the input was a multiple line input:
7
16
and the expected output is
49
256
The given code was
for line in sys.stdin:
# your code here
print(line, end="")
I tried to do ls = list(line.split()) but ls[0] is
['7']
['16']
and ls[1] is None
I also tried ls = list(line.split('\n')) but ls is
['7', '']
['16', '']
So how was I supposed to process the input to get ['7', '16'] rather than a 2 dimensional list?
From there I know how continue with make it an integer using map, creating a for loop for each item of the list and printing the square of each item.
I dont have a picture of the question since I was monitored on webcam but this is roughly what I remembered from the question.
edit: It was an online assessment platform so I am not sure exactly how the input was written as (like the raw input). Also I can only modify the code inside for line in sys.stdin:
Also, does anyone know how to write the input for sys.stdin using jupyternotebook such that I can practice this problem?
Problem is probably due to flushing of stdin since the \n lingers on.
as an alternative, use raw_input
while True:
c = raw_input('please enter a character: ')
print 'you entered', c
For the flushing part, see this
sys.stdin is line-buffered by default i.e., your sys.stdin.read(1) won't return until there is full line in stdin buffer.
It means if you enter a character and hit Enter then after you get the first character with sys.stdin.read(1), there is a newline in the buffer (one or two characters: os.linesep) that are read immediately on the next loop iterations.
You could avoid hitting Enter by reading exactly one character at a time (msvcrt.getch()).
It's simpler:
for line in sys.stdin:
chrCounter += len(line)
The file-like object sys.stdin is automatically iterated over line by line; if you call .readline() on it, you only read the first line (and iterate over that character-by-character); if you call read(), then you'll read the entire input into a single string and iterate over that character-by.character.
The answer from Tim Pietzcker is IMHO the correct one. There are 2 similar ways of doing this. Using:
for line in sys.stdin:
and
for line in sys.stdin.readlines():
The second option is closer to your original code. The difference between these two options is made clear by using e.g. the following modification of the for-loop body and using keyboard for input:
for line in sys.stdin.readlines():
line_len = len(line)
print('Last line was', line_len, 'chars long.')
chrCounter += len(line)
If you use the first option (for line in sys.stdin:), then the lines are processed right after you hit enter.
If you use the second option (for line in sys.stdin.readlines():), then the whole file is first read, split into lines and only then they are processed.
Hi, just wondering if using input() or sys.stdin is the preferred method for reading from stdin in python. What are the differences and what is more readable/pythonesque?
# Using input()
while True:
try:
line = input()
...
except EOFError:
break
# Using sys.stdin
for line in sys.stdin:
line = line.strip()
...Use the fileinput module:
import fileinput
for line in fileinput.input():
pass
fileinput will loop through all the lines in the input specified as file names given in command-line arguments, or the standard input if no arguments are provided.
Note: line will contain a trailing newline; to remove it use line.rstrip().
There's a few ways to do it.
sys.stdinis a file-like object on which you can call functionsreadorreadlinesif you want to read everything or you want to read everything and split it by newline automatically. (You need toimport sysfor this to work.)If you want to prompt the user for input, you can use
raw_inputin Python 2.X, and justinputin Python 3.If you actually just want to read command-line options, you can access them via the sys.argv list.
You will probably find this Wikibook article on I/O in Python to be a useful reference as well.