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

84

我发现了非常有用的语法。

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

当我想要在程序中指定输入文件或使用标准输入(stdin)时,我需要这两种方式。然而,并不总是需要输入文件。如果我没有使用-i或者重定向输入至其中之一

$ someprog | my_python_prog
$ my_python_prog < inputfile

我不想让我的Python程序等待输入。我希望它可以继续执行并使用默认值。

3个回答

144

Python标准库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'>)

6
我知道我之前说过类似的话,但这正是我所寻找的。谢谢。 - Justin Force
5
我感到十分困惑。OP说输入文件并不总是必需的,那么为什么要首先指定 infile 呢?这些位置参数有什么必要呢?最后,为什么 OP 的代码不能正常工作?argparse 教程似乎暗示它应该可以很好地工作... - 2rs2ts
1
@2rs2ts why is infile specified first? — 参数的特定顺序只是一种惯例,通常第一个参数用于指定输入,第二个参数用于指定输出。为什么这些参数位置固定? — 因为作者的偏好。使用位置参数没有任何问题。在需要从标准输入读取并写入文件的情况下,可能会有点尴尬,例如 app.py - outfile,但除此之外,位置参数将正常工作。为什么 OP 的代码不起作用? — 它实际上运行得很好 :) - Mr. Deathless
@Mr.Deathless,“app.py - outfile”解释得非常好,谢谢。 - 2rs2ts

24

使用isatty函数来检测你的程序是在交互式会话中还是从文件中读取:

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

然而,为了保持一致性和可再生性,如果文件名为-,考虑遵循规范并从stdin读取。您可能想要考虑让fileinput模块处理该问题。


20
建立在有关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))

好主意。这是最佳答案。 - a113nw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接