Python中的参数依赖项不能使i

2024-03-28 13:39:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在脚本中添加一个参数依赖项。其思想是--clone参数将需要非空的--gituser。在

在仔细阅读了this example之后,我尝试了以下方法

In [93]: class CloneAction(argparse.Action):
    ...:     def __call__(self, parser, namespace, _):
    ...:         if not namespace.git_user and namespace.clone:
    ...:             parser.error('"--clone" requires legal git user')
    ...:             
In [94]: parser = argparse.ArgumentParser()

In [95]: parser.add_argument('-g', '--gituser', dest='git_user', type=str, default='', action=CloneAction)
Out[95]: CloneAction(option_strings=['-g', '--gituser'], dest='git_user', nargs=None, const=None, default='', type=<type 'str'>, choices=None, help=None, metavar=None)

In [96]: parser.add_argument('--clone', action='store_true', default=False)
Out[96]: _StoreTrueAction(option_strings=['--clone'], dest='clone', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)

唉,这没用

^{pr2}$

我做错什么了?在


Tags: ingitnoneadddefaultparser参数clone
1条回答
网友
1楼 · 发布于 2024-03-28 13:39:32

这种参数间依赖关系在解析后更容易实现。在

args = parser.parse_args()
if not namespace.git_user and namespace.clone:
    parser.error('" clone" requires legal git user')

此时,git_user和{}都已被解析,并有它们的最终值。在

当您实现它时,只有当有一个 gituser参数时,才会运行自定义操作。所以我认为当你给它 gituser而没有 clone时,它会引起错误。在

您可以给 clone一个类似的自定义操作,但它还必须处理store_true的详细信息。那么 clone gituser value序列会发生什么呢?在分析clone值之前,clone操作将运行。像这样的测试会遇到一些棘手的论证顺序问题。在

还有几个问题:

  • 您的自定义操作不存储任何值,不管是否存在错误。最好自定义store子类。

  • 自定义操作应引发argparse.ArgumentError,而不是直接调用parser.error

unittest文件test/test_argparse.py有一个自定义操作的示例,其中包含这样的相互测试。但这只是一个玩具,验证这样的代码是允许的。在

=================

{{cd16>你可以实现 gituser,则parse_args的最终required操作测试将引发错误。但这需要保存对out[95]中显示的操作的引用(或者在parse._actions列表中找到它)。可行但混乱。在

=================

下面是一个来自test/test_argparse.py的一对交互自定义操作类的示例。在

^{pr2}$

NSargparse.Namespace的简写。在

class PositionalAction(argparse.Action):

    def __call__(self, parser, namespace, value, option_string=None):
        try:
            assert option_string is None, ('option_string: %s' %
                                           option_string)
            # check destination
            assert self.dest == 'badger', 'dest: %s' % self.dest
            # when argument is before option, spam=0.25, and when
            # option is after argument, spam=<whatever was set>
            expected_ns = NS(badger=2)
            if value in [42, 84]:
                expected_ns.spam = 0.25
            elif value in [1]:
                expected_ns.spam = 0.625
            elif value in [2]:
                expected_ns.spam = 0.125
            else:
                raise AssertionError('value: %s' % value)
            assert expected_ns == namespace, ('expected %s, got %s' %
                                              (expected_ns, namespace))
        except AssertionError:
            e = sys.exc_info()[1]
            raise ArgumentParserError('arg_action failed: %s' % e)
        setattr(namespace, 'badger', value)

它们用于

parser = argparse.ArgumentParser()
parser.add_argument('-s', dest='spam', action=OptionalAction,
        type=float, default=0.25)
parser.add_argument('badger', action=PositionalAction,
        type=int, nargs='?', default=2)

应该与:

'-s0.125' producing: NS(spam=0.125, badger=2)),
'42',                NS(spam=0.25, badger=42)),
'-s 0.625 1',        NS(spam=0.625, badger=1)),
'84 -s2',            NS(spam=2.0, badger=84)),

这是一个可以进行交叉检查的例子。但我要重复一次,一般来说,交互最好是在解析之后处理,而不是在解析期间。在

至于实现问题-如果用户没有给您 gituser,您的自定义操作永远不会被调用。只有在使用参数时才使用optionalAction.__call__positionals总是使用,但不是{}。在

相关问题 更多 >