idiomatic analogue of Perl's: while (<>) { ... }

Peter Otten __peter__ at web.de
Thu Sep 1 08:31:32 CEST 2011


Sahil Tandon wrote:

> I've been tasked with converting some programs from Perl -> Python, and
> am (as will soon be obvious) new to the language.  A few archive/google
> searches were inconclusive on a consensus approach, which is OK, but I
> just wonder if there is a more Python-esque way to do the following in
> Python 2.7.1:
> 
> %%
> # unbuffer STDOUT
> sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
> 
> # process input, line-by-line, and print responses after parsing input
> while 1:
>   rval = parse(raw_input())
>   if rval == None:
>     print('foo')
>   else:
>     print('bar')
> %%
> 
> This works, but while reading the documentation, I thought of using 'for
> line in fileinput.input()' in lieu of 'while 1:' construct.  This does
> not work when debugging the program on the command line -- the script
> appears to just hang no matter what is typed into STDIN.  I believe this
> is because of some internal buffering when using fileinput.  Is there a
> recommended way to disable such buffering?  Am I taking a totally wrong
> approach?
> 
> Feel free to just link me to previous discussions on the topic(s) if I
> have missed them.  Please be gentle with your cluebats. :-)

A quick look into fileinput.py reveals that it uses readlines() and slurps 
in the complete "file". I'm not sure that was a clever design decision...

Here's a partial reimplementation that should work for your use-case:

import sys
from itertools import chain

def _open_many(files):
    for file in files:
        if file == "-":
            yield sys.stdin
        else:
            with open(file) as f:
                yield f

def input(files=None, buffered=False):
    if files is None:
        files = sys.argv[1:]
    if not files:
        files = ["-"]
    files = _open_many(files)
    if not buffered:
        files = (iter(file.readline, "") for file in files)
    return chain.from_iterable(files)

for line in input():
    print line.strip().upper()





More information about the Python-list mailing list