使用argparse在Python中实现可选标准输入

85 投票
3 回答
33734 浏览
提问于 2025-04-17 03:14

我发现了一种非常有用的写法

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

可以用来指定输入文件或者使用标准输入(stdin)——这两种方式我在我的程序中都想用。不过,输入文件并不是每次都需要的。如果我没有使用 -i 或者没有用下面的方式重定向输入

$ someprog | my_python_prog
$ my_python_prog < inputfile

我不想让我的Python程序停下来等输入。我希望它能够继续运行,并使用默认值。

3 个回答

21

在之前关于TTY检测的回答基础上,为了明确回答这个问题:

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

可以使用 isatty判断 你的程序是否在一个交互式会话中,或者是在读取一个文件:

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

不过,为了保持一致性和可重复性,如果文件名是 -,建议遵循这个规范,从标准输入(stdin)读取数据。你可以考虑让 fileinput 模块来处理这个问题。

145

标准库的argparse文档提供了一个解决方案,可以让你选择性地输入或输出文件:

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

撰写回答