基于另一个选项的 argparse 默认选项 [英] argparse default option based on another option

查看:21
本文介绍了基于另一个选项的 argparse 默认选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 argparse python 脚本:

import argparse解析器 = argparse.ArgumentParser()parser.add_argument("--foo", required=True)

现在我想添加另一个选项--bar,它默认附加_BAR";到 --foo 参数指定的任何内容.

我的目标:

<预><代码>>>>parser.parse_args(['--foo', 'FOO'])>>>命名空间(foo='FOO', bar="FOO_BAR")

<预><代码>>>>parser.parse_args(['--foo', 'FOO', '--bar', 'BAR'])>>>命名空间(foo='FOO', bar="BAR")

我需要这样的东西:

parser.add_argument("--bar", default=get_optional_foo + "_BAR")

解决方案

这是编写自定义 Action 类的另一种尝试

import argparse类 FooAction(argparse.Action):# 改编自文档def __call__(self, parser, namespace, values, option_string=None):setattr(命名空间,self.dest,值)defaultbar = getattr(命名空间,'bar')尝试:defaultbar = defaultbar%values除了类型错误:# BAR 已经被替换经过setattr(命名空间,'bar',defaultbar)解析器 = argparse.ArgumentParser()parser.add_argument("--foo", required=True, action=FooAction)parser.add_argument("--bar", default="%s_BAR")args = parser.parse_args(['--foo', 'Foo', '--bar', 'Bar'])# 命名空间(bar='Bar', foo='Foo')args = parser.parse_args(['--foo', 'Foo'])# 命名空间(bar='Foo_BAR', foo='Foo')args = parser.parse_args(['--bar', 'Bar', '--foo', 'Foo'])# 命名空间(bar='Bar', foo='Foo')

请注意,该类必须知道 --bar 参数的 dest.此外,我使用 '%s_BAR' 来轻松区分默认值和非默认值.这处理了 --bar 出现在 --foo 之前的情况.

使这种方法复杂化的事情是:

  • add_argument 时间评估默认值.
  • 默认值放置在 parse_args 开头的命名空间中.
  • 标记(可选)参数可以以任何顺序出现
  • Action 类不是为处理交互参数而设计的.
  • bar 动作在默认情况下不会被调用.
  • bar 默认值可以是一个函数,但是必须在 parse_args 之后检查它是否需要计算.

虽然这个自定义操作可以解决问题,但我仍然认为我的另一个答案中的 addbar 函数是一个更简洁的解决方案.

Suppose I have an argparse python script:

import argparse

parser = argparse.ArgumentParser()
    
parser.add_argument("--foo", required=True)

Now I want to add another option --bar, which would default to appending "_BAR" to whatever was specified by --foo argument.

My goal:

>>> parser.parse_args(['--foo', 'FOO'])
>>> Namespace(foo='FOO', bar="FOO_BAR")

AND

>>> parser.parse_args(['--foo', 'FOO', '--bar', 'BAR'])
>>> Namespace(foo='FOO', bar="BAR")

I need something like this:

parser.add_argument("--bar", default=get_optional_foo + "_BAR")

解决方案

Here's another attempt at writing a custom Action class

import argparse
class FooAction(argparse.Action):
    # adapted from documentation
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        defaultbar = getattr(namespace, 'bar')
        try:
            defaultbar = defaultbar%values
        except TypeError:
            # BAR has already been replaced
            pass
        setattr(namespace, 'bar', defaultbar)

parser = argparse.ArgumentParser()
parser.add_argument("--foo", required=True, action=FooAction)
parser.add_argument("--bar", default="%s_BAR")

args = parser.parse_args(['--foo', 'Foo', '--bar', 'Bar'])
# Namespace(bar='Bar', foo='Foo')
args = parser.parse_args(['--foo', 'Foo'])
# Namespace(bar='Foo_BAR', foo='Foo')
args = parser.parse_args(['--bar', 'Bar', '--foo', 'Foo'])
# Namespace(bar='Bar', foo='Foo')

Note that the class has to know the dest of the --bar argument. Also I use a '%s_BAR' to readily distinguish between a default value, and a non default one. This handles the case where --bar appears before --foo.

Things that complicate this approach are:

  • default values are evaluated at add_argument time.
  • default values are placed in the Namespace at the start of parse_args.
  • flagged (optionals) arguments can occur in any order
  • the Action class is not designed to handle interacting arguments.
  • the bar action will not be called in the default case.
  • the bar default could be a function, but something would have to check after parse_args whether it needs to be evaluated or not.

While this custom Action does the trick, I still think the addbar function in my other answer is a cleaner solution.

这篇关于基于另一个选项的 argparse 默认选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆