Read from File, or STDIN
The fileinput module may do what you want - assuming the non-option arguments are in args
then:
import fileinputfor line in fileinput.input(args): print line
If args
is empty then fileinput.input()
will read from stdin; otherwise it reads from each file in turn, in a similar manner to Perl's while(<>)
.
In the simplest terms:
import sys# parse command lineif file_name_given: inf = open(file_name_given)else: inf = sys.stdin
At this point you would use inf
to read from the file. Depending on whether a filename was given, this would read from the given file or from stdin.
When you need to close the file, you can do this:
if inf is not sys.stdin: inf.close()
However, in most cases it will be harmless to close sys.stdin
if you're done with it.
I like the general idiom of using a context manager, but the (too) trivial solution ends up closing sys.stdin
when you are out of the with
statement, which I want to avoid.
Borrowing from this answer, here is a workaround:
import sysimport contextlib@contextlib.contextmanagerdef _smart_open(filename, mode='Ur'): if filename == '-': if mode is None or mode == '' or 'r' in mode: fh = sys.stdin else: fh = sys.stdout else: fh = open(filename, mode) try: yield fh finally: if filename != '-': fh.close() if __name__ == '__main__': args = sys.argv[1:] if args == []: args = ['-'] for filearg in args: with _smart_open(filearg) as handle: do_stuff(handle)
I suppose you could achieve something similar with os.dup()
but the code I cooked up to do that turned out to be more complex and more magical, whereas the above is somewhat clunky but very straightforward.