我做了尽可能多的研究但是我没有找到最好的方法来使某些cmdline参数仅在某些条件下是必要的,在这种情况下只有在给出其他参数的情况下.这是我想要在一个非常基本的层面上做的事情:
p = argparse.ArgumentParser(description='...')
p.add_argument('--argument', required=False)
p.add_argument('-a', required=False) # only required if --argument is given
p.add_argument('-b', required=False) # only required if --argument is given
Run Code Online (Sandbox Code Playgroud)
从我所看到的,其他人似乎只是在最后添加自己的支票:
if args.argument and (args.a is None or args.b is None):
# raise argparse error here
Run Code Online (Sandbox Code Playgroud)
有没有办法在argparse包中本地执行此操作?
Mir*_*ira 35
一段时间以来,我一直在寻找这个问题的简单答案.您需要做的就是检查是否'--argument'存在sys.argv,所以基本上您可以执行以下代码示例:
import argparse
import sys
if __name__ == '__main__':
p = argparse.ArgumentParser(description='...')
p.add_argument('--argument', required=False)
p.add_argument('-a', required='--argument' in sys.argv) #only required if --argument is given
p.add_argument('-b', required='--argument' in sys.argv) #only required if --argument is given
args = p.parse_args()
Run Code Online (Sandbox Code Playgroud)
这种方式required接收True或False取决于用户是否使用--argument.已经测试了它,似乎工作,并保证-a和-b相互之间的独立行为.
che*_*ner 10
您可以通过提供自定义操作来实现检查--argument,该操作将使用其他关键字参数来指定--argument在使用时应该成为哪些其他操作.
import argparse
class CondAction(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
x = kwargs.pop('to_be_required', [])
super(CondAction, self).__init__(option_strings, dest, **kwargs)
self.make_required = x
def __call__(self, parser, namespace, values, option_string=None):
for x in self.make_required:
x.required = True
try:
return super(CondAction, self).__call__(parser, namespace, values, option_string)
except NotImplementedError:
pass
p = argparse.ArgumentParser()
x = p.add_argument("--a")
p.add_argument("--argument", action=CondAction, to_be_required=[x])
Run Code Online (Sandbox Code Playgroud)
确切的定义CondAction将取决于究竟--argument应该做什么.但是,例如,如果--argument是一个常规的,采取一个参数和保存它的动作类型,那么只需继承argparse._StoreAction就足够了.
在该示例性解析器,我们保存到一个参考--a内部选项--argument的选择,并且当--argument被看作在命令行上,它设置required标志上--a到True.处理完所有选项后,argparse验证是否已设置标记为必需的任何选项.
pab*_*ouk 10
这是一个简单干净的解决方案,具有以下优点:
in sys.argv。argparse.Action或argparse.UsageGroup类。我注意到一个相当大的缺点(有些人可能会认为这是可取的):帮助文本根据决定参数的状态而变化。
这个想法是使用argparse两次:
in sys.argv测试的使用。为此,我们使用一个不显示帮助的简短解析器和.parse_known_args()忽略未知参数的方法。import argparse
# First parse the deciding arguments.
deciding_args_parser = argparse.ArgumentParser(add_help=False)
deciding_args_parser.add_argument(
'--argument', required=False, action='store_true')
deciding_args, _ = deciding_args_parser.parse_known_args()
# Create the main parser with the knowledge of the deciding arguments.
parser = argparse.ArgumentParser(
description='...', parents=[deciding_args_parser])
parser.add_argument('-a', required=deciding_args.argument)
parser.add_argument('-b', required=deciding_args.argument)
arguments = parser.parse_args()
print(arguments)
Run Code Online (Sandbox Code Playgroud)
您的解析后测试很好,特别是如果默认测试is None适合您的需求。
http://bugs.python.org/issue11588 'Add "necessarily inclusive" groups to argparse'研究使用该groups机制(mutual_exclusive_groups 的概括)来实现这样的测试。
我已经编写了一组UsageGroups实现测试,例如xor(互斥)and、、、or和not。我认为这些内容很全面,但我无法用这些操作来表达你的情况。(看起来我需要nand- 不是,见下文)
该脚本使用一个自定义Test类,它本质上实现了您的解析后测试。 seen_actions是解析已看到的操作列表。
class Test(argparse.UsageGroup):
def _add_test(self):
self.usage = '(if --argument then -a and -b are required)'
def testfn(parser, seen_actions, *vargs, **kwargs):
"custom error"
actions = self._group_actions
if actions[0] in seen_actions:
if actions[1] not in seen_actions or actions[2] not in seen_actions:
msg = '%s - 2nd and 3rd required with 1st'
self.raise_error(parser, msg)
return True
self.testfn = testfn
self.dest = 'Test'
p = argparse.ArgumentParser(formatter_class=argparse.UsageGroupHelpFormatter)
g1 = p.add_usage_group(kind=Test)
g1.add_argument('--argument')
g1.add_argument('-a')
g1.add_argument('-b')
print(p.parse_args())
Run Code Online (Sandbox Code Playgroud)
示例输出为:
1646:~/mypy/argdev/usage_groups$ python3 issue25626109.py --arg=1 -a1
usage: issue25626109.py [-h] [--argument ARGUMENT] [-a A] [-b B]
(if --argument then -a and -b are required)
issue25626109.py: error: group Test: argument, a, b - 2nd and 3rd required with 1st
Run Code Online (Sandbox Code Playgroud)
usage错误消息仍然需要处理。它不会做任何解析后测试不能做的事情。
如果 ,您的测试会引发错误(argument & (!a or !b))。反之,允许的是!(argument & (!a or !b)) = !(argument & !(a and b))。nand通过向我的课程添加测试UsageGroup,我可以将您的案例实现为:
p = argparse.ArgumentParser(formatter_class=argparse.UsageGroupHelpFormatter)
g1 = p.add_usage_group(kind='nand', dest='nand1')
arg = g1.add_argument('--arg', metavar='C')
g11 = g1.add_usage_group(kind='nand', dest='nand2')
g11.add_argument('-a')
g11.add_argument('-b')
Run Code Online (Sandbox Code Playgroud)
用法是(用于!()标记“nand”测试):
usage: issue25626109.py [-h] !(--arg C & !(-a A & -b B))
Run Code Online (Sandbox Code Playgroud)
我认为这是使用通用用途组来表达这个问题的最短、最清晰的方式。
在我的测试中,成功解析的输入是:
''
'-a1'
'-a1 -b2'
'--arg=3 -a1 -b2'
Run Code Online (Sandbox Code Playgroud)
应该引发错误的是:
'--arg=3'
'--arg=3 -a1'
'--arg=3 -b2'
Run Code Online (Sandbox Code Playgroud)
对于争论,我想出了一个像这样的快速解决方案。假设:(1)“--help”应该显示帮助而不是抱怨所需的参数(2)我们正在解析sys.argv
p = argparse.ArgumentParser(...)
p.add_argument('-required', ..., required = '--help' not in sys.argv )
Run Code Online (Sandbox Code Playgroud)
可以轻松修改它以匹配特定设置。对于所需的位置(如果例如在命令行上给出“--help”,则将不再需要)我提出了以下建议:[位置不允许使用关键字参数required=...!]
p.add_argument('pattern', ..., narg = '+' if '--help' not in sys.argv else '*' )
Run Code Online (Sandbox Code Playgroud)
基本上,如果指定了“--help”,这会将命令行上所需的“模式”出现次数从一个或多个变为零个或多个。
| 归档时间: |
|
| 查看次数: |
13150 次 |
| 最近记录: |