允许 argument/option 覆盖位置参数

Allow argument/option to override positional argument

我正试图在我的 argparse 解析器中进行排除。基本上我想要的是避免 --all 选项和 filenames 参数被解析(我认为成功了)。

但我还想创建另一个检查,如果我只传递 python reader.py read --allfilenames 参数将填充当前目录中的所有 txt 文件。

到目前为止,我已经想出了以下代码:

import argparse
import glob

parser = argparse.ArgumentParser()
subcommands = parser.add_subparsers(title='subcommands')

read_command = subcommands.add_parser('read')
read_command.add_argument('filenames', type=argparse.FileType(), nargs = '+')
read_command.add_argument('-a', '--all', action='store_true')

parsed = parser.parse_args()

if parsed.all and parsed.filenames:
    raise SystemExit

if parsed.all:
    parsed.filenames = glob.glob('*.txt')

print parsed

问题是,如果我尝试 运行 python reader.py read --all,由于 filenames 参数,我会得到错误 error: too few arguments

  1. 有没有一种方法可以像我想要的那样工作,而无需为 read 创建子命令,例如 python reader.py read all?

  2. 如何访问 argparse 中的错误消息?我想要一些默认消息,说 filenames--all 不能组合而不是 SystemExit 错误。

此外,我想避免使用 add_mutually_exclusive_group,因为这只是我的真实解析器的一个片段,这种方法在其中不起作用(已在其他 SO 主题中检查过)。

我听说过自定义操作,但看到它的示例真的很有帮助。

如果 filenames 得到 nargs="*",它应该允许您单独使用 --allparsed.filenames 将成为 [],您可以将其替换为 glob

您也可以测试给该参数一个从 glob 派生的 default - 但请参阅我关于 FileType.

的警告

你想让解析器打开你给它的所有文件名吗?或者您宁愿自己打开文件(最好在 with 上下文中)。 FileType 打开文件(必要时创建),并在此过程中检查它们是否存在(这很好),但由您(或程序退出)关闭它们。

文档讨论了自己发出错误信息,以及如何更改它们。 parser.error('my message') 显示用法和消息,然后退出。

if parsed.all and parsed.filenames:
    parsed.error("Do you want to read ALL or just %s?"%parsed.filenames)

也可以在 try/except 子句中捕获 SystemExit 异常。