python argparse - either both optional arguments or else neither one

自作多情 提交于 2019-11-30 04:49:56

I believe that the best way to handle this is to post-process the returned namespace. The reason that argparse doesn't support this is because it parses arguments 1 at a time. It's easy for argparse to check to see if something was already parsed (which is why mutually-exclusive arguments work), but it isn't easy to see if something will be parsed in the future.

A simple:

parser.add_argument('-n','--name',...,default=None)
parser.add_argument('-p','--password',...,default=None)
ns = parser.parse_args()

if len([x for x in (ns.name,ns.password) if x is not None]) == 1:
   parser.error('--name and --password must be given together')

name = ns.name if ns.name is not None else "default_name"
password = ns.password if ns.password is not None else "default_password"

seems like it would suffice.

I know this is more than two years late, but I found a nice and concise way to do it:

if bool(ns.username) ^ bool(ns.password):
    parser.error('--username and --password must be given together')

^ is the XOR operator in Python. To require both arguments given at the command line is essentially an XOR test.

This is probably how I'd do it. Since you have existing defaults with the option to change, define the defaults, but don't use them as your argument defaults:

default_name = "x"
default_pass = "y"
parser.add_argument(
    '-n',
    '--name',
    default=None,
    help='the login name that you wish the program to use'
    )

parser.add_argument(
    '-p',
    '--password',
    default=None,
    help='the password to log in with.'
    )
args = parser.parse_args()
if all(i is not None for i in [args.name, args.password]):
    name = args.name
    passwd = args.password
elif any(i is not None for i in [args.name, args.password]):
    parser.error("Both Name and Password are Required!")
else:
    name = default_name
    passwd = default_pass
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!