如何在 Python 的 argparse 中相互排除多个参数

How to mutually exclude multiple arguments in Python's argparse

我已经阅读了很多教程、问题和文档,但无法弄清楚如何实现这一点:

prog.py [-h] [-d DEVICE -l | (-m M -s S -p P)]

使用 -l 参数时,prog.py 从设备接口读取。当提供 -m, -s and/or -p, prog.py 写入该接口。读写不能同时进行,所以读写参数是互斥的。

一旦指定了 DEVICE,就需要提供 -l 或 -m、-s 或 -p 中的至少一个,也应该可以提供这三者的任意组合。

到目前为止,我从多个角度解决了这个问题:

这是我最后试过的:

import argparse
import sys

parser = argparse.ArgumentParser()
parser.add_argument("-d","--device",
        default="system",
        help="foo")

subparsers = parser.add_subparsers(help='foo')

read_parser = subparsers.add_parser('read', help='foo')
read_parser.add_argument("-l", "--list",
        action="store_true")

write_parser = subparsers.add_parser("write", help="bar")
write_parser.add_argument("-m","--mode",
        type=str,
        choices=["on","off","auto"],
        help="foo")
write_parser.add_argument("-s", "--season",
        type=str,
        choices=["winter","summer"],
        help="foo")
write_parser.add_argument("-p","--present",
        type=int,
        choices=[0,1],
        help="foo")
parser.parse_args()

这甚至不接近 argparse 期望读取或写入的子解析器。我需要做的是添加互斥的组。有人知道如何解决这个问题吗?

您可以自行检查(使用基本的 argparse 功能)是否传递了正确的参数组合:

parser = argparse.ArgumentParser()

parser.add_argument("-d","--device",
    default="system",
    help="foo")
parser.add_argument("-l", "--list",
    action="store_true")
parser.add_argument("-m","--mode",
    type=str,
    choices=["on","off","auto"],
    help="foo")
parser.add_argument("-s", "--season",
    type=str,
    choices=["winter","summer"],
    help="foo")
parser.add_argument("-p","--present",
    type=int,
    choices=[0,1],
    help="foo")
args = parser.parse_args()

# if user defines device but not any read/write argument raise exception
if args.device is not None and not args.list and all(arg is None for arg in (args.season, args.present, args.mode)):
    parser.error('Wrong arguments passed')

# if user defines read and write arguments at the same time raise exception
if args.list and not all(arg is None for arg in (args.season, args.present, args.mode)):
    parser.error('Wrong arguments passed')