禁止 argparse 参数被覆盖

Disable argparse arguments from being overwritten

我有一个遗留 Python 应用程序,它使用 argparse 在其 CLI 中使用一些选项,例如:

parser = argparse.ArgumentParser()
parser.add_argument('-f', default='foo')

现在我需要删除这个选项,因为现在它的值不能被用户覆盖,但它必须采用默认值(比如示例中的 'foo')。有没有办法保留选项但防止它显示并被用户覆盖(这样我就可以保持其余代码不变)?

是的,你可以做到。解析器解析后(args = parser.parse_args())是一个NameSpace所以可以这样做:

parser = argparse.ArgumentParser()
args = parser.parse_args()
args.foo = 'foo value'
print(args)
>>> Namespace(OTHER_OPTIONS, foo='foo value')

我假设您想将 test 添加到您的解析器,因此您的原始代码仍然有效,但您不希望它作为用户的一个选项。

我认为 argparse 模块将此作为标准选项提供没有意义,但有几种简单的方法可以实现您想要的。

最明显的方法是在调用 parse_args() 之后覆盖该值(正如评论和另一个答案中已经提到的那样):

args.f = 'foo'

但是,用户可能不知道该选项不再受支持,应用程序现在假定 值“foo”。根据用例,最好就此警告用户。 argparse 模块有几个选项可以做到这一点。

另一种可能性是使用 Action class 来施展魔法。例如,如果用户提供的选项不再受支持,您可以打印警告,甚至可以使用 built-in 错误处理。

import argparse

class FooAction(argparse.Action):

    def __call__(self, parser, namespace, values, option_string=None):
        if values != 'foo':
            print('Warning: option `-f` has been removed, assuming `-f foo` now')
            # Or use the built-in error handling like this:
            # parser.error('Option "-f" is not supported anymore.')

        # You could override the argument value like this:
        # setattr(namespace, self.dest, 'foo')

parser = argparse.ArgumentParser()
parser.add_argument('-f', default='foo', action=FooAction)
args = parser.parse_args()
print('option=%s' % args.f)

您也可以将选择限制为仅“foo”,并让 argparse 为其他值创建错误:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', default='foo', choices=['foo'])
args = parser.parse_args()
print('option=%s' % args.f)

调用 python test.py -f bar 将导致:

usage: test.py [-h] [-f {foo}]
test.py: error: argument -f: invalid choice: 'bar' (choose from 'foo')

不完全清楚您可以做什么,而不是使用解析器。你能编辑设置吗?还是只修改解析结果?

如果您可以编辑设置,则可以将 add_argument 行替换为

parser.setdefaults(f='foo')

https://docs.python.org/3/library/argparse.html#parser-defaults

-f不会出现在用法或帮助中,但会出现在args

或者您可以保留它,但禁止显示帮助

parser.add_argument('-f', default='foo', help=argparse.SUPPRESS)

https://docs.python.org/3/library/argparse.html#help

设置解析后的值也可以