Optional stdin in Python with argparse

PythonStdinArgparse

Python Problem Overview


I found the very useful syntax

parser.add_argument('-i', '--input-file', type=argparse.FileType('r'), default='-')

for specifying an input file or using stdin—both of which I want in my program. However, the input file is not always required. If I'm not using -i or redirecting input with one of

$ someprog | my_python_prog
$ my_python_prog < inputfile

I don't want my Python program to wait for input. I want it to just move along and use default values.

Python Solutions


Solution 1 - Python

The standard library documentation for argparse suggests this solution to allow optional input/output files:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
...                     default=sys.stdin)
>>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
...                     default=sys.stdout)
>>> parser.parse_args(['input.txt', 'output.txt'])
Namespace(infile=<_io.TextIOWrapper name='input.txt' encoding='UTF-8'>,
          outfile=<_io.TextIOWrapper name='output.txt' encoding='UTF-8'>)
>>> parser.parse_args([])
Namespace(infile=<_io.TextIOWrapper name='<stdin>' encoding='UTF-8'>,
          outfile=<_io.TextIOWrapper name='<stdout>' encoding='UTF-8'>)

Solution 2 - Python

Use http://docs.python.org/library/os.html#os.isatty">isatty</a> to https://stackoverflow.com/questions/1077113/how-do-i-detect-whether-sys-stdout-is-attached-to-terminal-or-not">detect</a> whether your program is in an interactive session or reading from a file:

if not sys.stdin.isatty(): # Not an interactive device.
  # ... read from stdin

However, for the sake of consistency and reproducability, consider following the norm and reading from stdin if the filename is -. You may want to consider to let the http://docs.python.org/library/fileinput.html">`fileinput`</a> module handle that.

Solution 3 - Python

Building on top of the answer regarding TTY detection, to answer the question explicitly:

import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input-file', type=argparse.FileType('r'), default=(None if sys.stdin.isatty() else sys.stdin))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJustin ForceView Question on Stackoverflow
Solution 1 - PythonmikewatersView Answer on Stackoverflow
Solution 2 - PythonphihagView Answer on Stackoverflow
Solution 3 - PythonpalswimView Answer on Stackoverflow