87

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.

3 Answers 3

150

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'>)
Sign up to request clarification or add additional context in comments.

4 Comments

I'm absolutely bewildered. OP said the input file was not always required. So why is infile specified first? Why are these positional anyway? Lastly, why the heck wouldn't OP's code work? The argparse tutorial seems to imply that it should work just fine...
@2rs2ts why is infile specified first? — Particular ordering of the arguments is just a convention, you usually expect first argument to specify an input and second specify output. Why are these positional anyway? — Because of author's preference. Nothing wrong with this usage of positional arguments. Might be a bit awkward to use in scenario when you want to read from stdin and write to a file, i.e.app.py - outfile but other than that positional argument would work just fine. Why the heck wouldn't OP's code work? — it actually works just fine :)
@Mr.Deathless app.py - outfile explains it perfectly, thank you.
argparse.FileType is being deprecated with Python 3.14.
25

Use isatty to detect 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 fileinput module handle that.

Comments

23

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.