Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python iterate over stdin line by line using input()

I am trying to get multiple names separated by newlines from the console and put them into a variable. Let's assume I want to get input from the terminal forever (I'll add some code to break out of the loop later). I know how to do it with a while loop and recursion, but I would like to be able to do it with a for loop.

In the below example when I get "peter" as input from the terminal I get each letter rather than a whole line at a time:

for name in input():
    print(name)

Now, if I use sys.stdin the name variable becomes "peter\n":

for name in sys.stdin:
    print(name)

Is there a easy way to get input() to give "name" a whole line rather than individual characters? Or just by the nature of using for in I am going to be iterating through the characters in the input? Are there any inherent risks/problems with getting input in this fashion? Is there a "standard" way of getting input in a situation like this?

I am using Python 3.5.1 on Ubuntu 15.10.

like image 211
PeterH Avatar asked Jan 30 '16 01:01

PeterH


1 Answers

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.

like image 91
ShadowRanger Avatar answered Sep 20 '22 21:09

ShadowRanger