Python argparse:参数同时支持可选和位置值

5 投票
1 回答
2951 浏览
提问于 2025-04-17 15:41

考虑一下以下的用法:

usage: do.py [-h] [-s | -m] filename

这不是完整的用法。但我想要的是,filename 应该是一个实际的文件值,而不是:

--filename FILENAME

另外,filename 也应该是可选的,这样我就可以从标准输入读取内容。想想 UNIX 系统上的 cat 程序。

你只需要这样说:

cat filename

或者

cat

编辑:现在,如果我执行程序 do.py 而不提供任何命令行选项,我会收到一个 error: too few arguments 的错误提示。相反,我希望即使不提供有效的 filename,程序也能执行。我该怎么做呢?

1 个回答

7

更新 2: 根据 ArgParse 的文档,

nargs='?' 的一个常见用法是允许输入和输出文件为可选项:

>>> 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=<open file 'input.txt', mode 'r' at 0x...>,
          outfile=<open file 'output.txt', mode 'w' at 0x...>)
>>> parser.parse_args([])
Namespace(infile=<open file '<stdin>', mode 'r' at 0x...>,
          outfile=<open file '<stdout>', mode 'w' at 0x...>)

原始回答:

这很简单:只需添加一个位置参数,并设置一个默认值和 nargs='*'。如果没有提供任何参数,就会使用默认值;否则,将使用命令行上提供的参数:

>>> p = argparse.ArgumentParser()
>>> p.add_argument('filename', nargs='*', default=['-'])
>>> p.parse_args([])
Namespace(filename=['-'])
>>> p.parse_args(['abc'])
Namespace(filename=['abc'])

通常,- 用来表示标准输入和标准输出。

然后你可以这样做:

def get_inputs(ns):
    """Iterate over input files."""
    for path in ns.filename:
        if path == '-':
            yield sys.stdin
        else:
            yield open(path, 'r')

更新: 我假设你想要多个文件名,因为 cat 命令可以接受多个文件名。如果你只想要零个或一个文件名,可以使用 nargs='?'

撰写回答