如何将 ArgumentParser 与两个都接受 nargs='*' 的短可选参数一起使用

How to use ArgumentParser with two short optional arguments which both accept nargs='*'

我正在尝试为我的项目配备从 cli 控制的日志记录功能。为此,我使用 ArgumentParser 来解析标志“-v”以进行冗长和“-d”以进行调试。应该可以在它们后面指定可选的名称空间。请参阅下面的代码段。问题在最后。

parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose',
                    dest='verbose',
                    metavar='namespace',
                    nargs='*',
                    help='Sets the logging level to INFO.')
parser.add_argument('-d', '--debug,
                    dest='debug',
                    metavar='namespace',
                    nargs='*',
                    help='Sets the logging level to DEBUG.')

args = parser.parse_args()
if args.verbose:
   print('verbose: ', args.verbose)
if args.debug:
   print('debug: ', args.debug)

因此帮助用法类似于:

optional arguments:
   -v [namespace [namespace ...]]
   -d [namespace [namespace ...]]

我将它与类似下面的代码片段的内容一起使用。这只是您了解我的意图的背景信息。

logging_level = logging.INFO  # just as example for -v
if not namespace:
   logger = logging.getLogger()
   logger.setLevel(logging_level)
else:
   for n in namespace:
      child_logger = logger.getChild(f'{root_module_name}.{namespace}')
      child_logger.setLevel(logging_level)

问题

1.) 如果我调用 python my_module.py -v A -d B 输出会像预期的那样:

verbose: ['A']
debug: ['B']



2.) 如果我调用 python my_module.py -v -d 输出会像预期的那样:

verbose: []
debug: []



3.) 但是如果我调用 python my_module.py -vd 输出看起来像:

verbose: ['d']
debug: None

我要实现的是:

verbose: []
debug: []



4.) 如果我称它为 python my_module.py -vd B

会变得更糟
error: unrecognized arguments: B

我要实现的是:

verbose: []
debug: ['B']

问题 是如何实现我想要的行为 3.) 和 4.)?

我知道我可以使用符合我要求的 python my_module.py --verbose --debug B 绕过这个问题。但这不是我要问的。

最简单的解决方案是不使用“-vd”输入。

'-vd' 被解析为 `-v d'。由于“-v”是一个带参数的短选项,它将以下字符串解释为一个值,而不是另一个标志。

您会期望“-vb”产生 ['b'],对吧?为什么它对待“-vd”有什么不同?

人们更经常抱怨“-v -d”未能将“-d”视为“-v”的参数(通常是“-v”需要一个参数)。

'-vd' 将被解析为 '-v -d' 如果 '-v' 没有参数,例如如果它是 'store_true' (nargs=0).

https://docs.python.org/3/library/argparse.html#option-value-syntax

For short options (options only one character long), the option and its value can be concatenated:

Several short options can be joined together, using only a single - prefix, as long as only the last option (or none of them) requires a value: