How to read from stdin or from a file if no data is piped in Python?

e-satis picture e-satis · Feb 15, 2010 · Viewed 9.4k times · Source

I have a CLI script and want it to read data from a file. It should be able to read it in two ways :

  • cat data.txt | ./my_script.py
  • ./my_script.py data.txt

—a bit like grep, for example.

What I know:

  • sys.argv and optparse let me read any args and options easily.
  • sys.stdin let me read data piped in
  • fileinput make the full process automatic

Unfortunately:

  • using fileinput uses stdin and any args as input. So I can't use options that are not filenames as it tries to open them.
  • sys.stdin.readlines() works fine, but if I don't pipe any data, it hangs until I enter Ctrl + D
  • I don't know how to implement "if nothing in stdin, read from a file in args" because stdin is always True in a boolean context.

I'd like a portable way to do this if possible.

Answer

sykora picture sykora · Feb 15, 2010

Argparse allows this to be done in a fairly easy manner, and you really should be using it instead of optparse unless you have compatibility issues.

The code would go something like this:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')

Now you have a parser that will parse your command line arguments, use a file if it sees one, or use standard input if it doesn't.