Argparse - 子解析器中位置参数之前的可选参数

Posted

技术标签:

【中文标题】Argparse - 子解析器中位置参数之前的可选参数【英文标题】:Argparser - optional argument before positional argument in a subparser 【发布时间】:2020-11-10 01:18:45 【问题描述】:

我想在这样的位置参数之前使用带有可选参数的脚本:

script.py ls --fruit 苹果厨房

“ls”是如下子命令 “fruit”是可选的,可能存在也可能不存在 “厨房”是我的位置,我将其命名为“位置”
parser_ls = subparsers.add_parser('ls', help='Lists all fruits in the location', add_help=False)
parser_ls.add_argument('--fruit', type=str, dest="fruits", nargs='?')    
parser_ls.add_argument('location', nargs=argparse.REMAINDER)

目前我尝试使用 nargs=argparse.REMAINDER 作为“位置”,但我将获得位置命名空间中的所有值和水果中的 None,这不是我想要的。

Namespace(location=['--fruits', 'apple', 'kitchen'], help_down=False, fruits=None)

【问题讨论】:

嗨,如果我用 * 替换 REMAINDER,它不会看到我的“位置”值,除非我把它放在第一个作为“ls kitchen --fruits apple”,但我想得到“ls ——水果苹果厨房”。有什么想法吗? 【参考方案1】:

使用您的代码:

In [206]: p=argparse.ArgumentParser()                                                                
In [207]: sp=p.add_subparsers(dest='cmd')                                                            

In [209]: parser_ls = sp.add_parser('ls', help='Lists all fruits in the location', add_help=False) 
     ...: parser_ls.add_argument('--fruit', type=str, dest="fruits", nargs='?');     
     ...: parser_ls.add_argument('location', nargs=argparse.REMAINDER);                              

我得到一个不同的命名空间。 fruits 确实得到了字符串。 REMAINDER 只得到一个字符串。

In [210]: p.parse_args('ls --fruit apple kitchen'.split())                                           
Out[210]: Namespace(cmd='ls', fruits='apple', location=['kitchen'])

只是检查一下,您使用的是哪个 python 版本?

脚本

将此代码移动到脚本中:

import argparse
p=argparse.ArgumentParser()                                                                
sp=p.add_subparsers(dest='cmd')                                                            

parser_ls = sp.add_parser('ls', help='Lists all fruits in the location', add_help=False) 
parser_ls.add_argument('--fruit', type=str, dest="fruits", nargs='?')    
parser_ls.add_argument('location', nargs=argparse.REMAINDER)

args = p.parse_args()
print(args)

测试用例:

1443:~/mypy$ python3 stack63001317.py 
Namespace(cmd=None)
1139:~/mypy$ python3 stack63001317.py ls
Namespace(cmd='ls', fruits=None, location=[])
1139:~/mypy$ python3 stack63001317.py ls --fruit apple kitchen
Namespace(cmd='ls', fruits='apple', location=['kitchen'])

【讨论】:

我使用的是 Python 3.8。编码时如何使用 .split?目前我的解析看起来像 args = parser.parse_args()。我收到错误“错误:无法识别的参数:位置” 我正在使用 '....'.split() 生成测试输入,而不是从默认的 sys.argv[1:] 中获取它。 那么为什么我会得到一个不同的命名空间呢?我现在重新运行并且仍然得到'python3.8 script.py ls --fruit apple kitchen'“命名空间(位置= ['ls','--fruit','apple','kitchen'],help_down = False,fruits =无)” 我也尝试了上面的代码,我得到的是“Namespace(fruits=None, location=['ls', '--fruit', 'apple', 'kitchen' ])" 所以这是同一个问题。我认为你会因为分裂而得到不同的结果。我如何将其合并到上面的代码中?谢谢! 另一件事是,如果我打印位置的 len,它会显示 1,所以我认为这是一个错误,如果我打印 args.fruits,我会得到正确的值“apple”无...

以上是关于Argparse - 子解析器中位置参数之前的可选参数的主要内容,如果未能解决你的问题,请参考以下文章

带有多级解析器/子解析器的 Argparse 可选参数

Argparse:具有可变参数的选项的可选参数

使用不需要指定输出文件名的可选参数运行 argparse

argparse 仅在位置参数之前解析

argparse 未正确处理子解析器中的缩写

在子解析器之后停止解析