Python Argparse:获取用于命名空间变量的命令行参数
Posted
技术标签:
【中文标题】Python Argparse:获取用于命名空间变量的命令行参数【英文标题】:Python Argparse: Get the command-line argument used for a Namespace variable 【发布时间】:2021-12-23 08:00:22 【问题描述】:是否有适当的或至少更好的方法来获取用于设置命名空间参数(属性)值的命令行参数?
我目前正在使用这样的东西:
>>> import argparse
>>>
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--do-a', '-a',
... default=False, action='store_true',
... dest='process_foo',
... help="Do some awesome a to the thing.")
>>> args = parser.parse_args()
>>>
>>> def get_argument(parser, dest):
... for action in parser._actions:
... if action.dest == dest:
... return action.option_strings[0], action.help
... return dest, ''
...
>>> get_argument(parser, 'process_foo')
('--do-a', 'Do some awesome a to the thing.')
这可能适用于 99% 的情况;但是,如果多个命令行参数可以设置process_foo
,这将不起作用,并且访问“隐藏”实例属性(parser._actions
)充其量是笨拙的。有没有更好的方法来做到这一点?
我将此添加到一个模块中,所有数据科学流程都会继承哪些日志环境和其他内容,以便我们具有更好的可重复性。有问题的模块已经自动记录设置、参数、命令行参数等,但在某些方面不是很友好。
【问题讨论】:
为什么不直接使用args.process_foo
?这不适用于您的应用程序吗?
【参考方案1】:
我建议创建您自己的从argarse.Action 派生的操作类,它不仅将解析值存储在命名空间中,还将解析值的选项字符串存储在命名空间中。
完整的工作示例:
import argparse
class StoreTrueWithOptionStringAction(argparse.Action):
def __init__(self,
option_strings,
dest,
default=None,
required=False,
help=None,
metavar=None):
super().__init__(option_strings=option_strings,
dest=dest,
nargs=0,
const=True,
default=default,
required=required,
help=help)
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.const)
if option_string is not None:
setattr(namespace, f'self.dest_option_string', option_string)
def get_parser():
parser = argparse.ArgumentParser()
parser.add_argument('--bar', action=StoreTrueWithOptionStringAction, dest='foo', default=False)
parser.add_argument('--baz', action=StoreTrueWithOptionStringAction, dest='foo', default=False)
return parser
def main():
parser = get_parser()
args = parser.parse_args()
print(args.foo)
print(args.foo_option_string)
if __name__ == '__main__':
main()
输出:
$ python3 main.py --bar
True
--bar
$ python3 main.py --baz
True
--baz
【讨论】:
【参考方案2】:不用担心_actions
的“隐藏性”。这是存储对由add_argument
创建的所有Actions
的引用的主要列表。您不应该摆弄列表,但您当然可以使用它来收集信息。
add_argument
创建一个Action
对象,将其放入_actions
(通过_add_action
方法),并返回它。如果您不喜欢使用_actions
,您可以使用add_argument
返回的对象收集您自己的引用列表。
我从_add_action
看到,它还将标记的操作放入self._option_string_actions
字典中,从而更容易将选项字符串与其action
配对。
解析不会对parser
、其属性或actions
进行任何更改。虽然它有各种局部变量(在_parse_known_args
方法中),但唯一改变的是args
命名空间。
它使对args
的访问尽可能通用,包括getattr
、setattr
和hasattr
。这包括在解析开始时设置默认值。解析器不会记录哪个选项字符串触发了特定的take_action
和随后的setattr
。然而Action
的__call__
确实得到了字符串。对于最常见的“store_action”,调用是
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, values)
我认为所有定义的Action
子类都使用self.dest
,但用户定义的子类不必这样做。他们甚至可以设置其他命名空间属性,或者不设置(例如 help 没有设置任何东西)。他们还可以记录option_string
。
也可以设置命名空间属性而不通过定义的操作。你的dest
测试对这些没有帮助。
https://docs.python.org/3/library/argparse.html#parser-defaults
展示了如何在不在参数中定义属性的情况下设置属性。子命令显示了如何使用它来定义将与特定解析器一起使用的函数。
https://docs.python.org/3/library/argparse.html#the-namespace-object 还表明可以提供部分初始化的命名空间。
【讨论】:
以上是关于Python Argparse:获取用于命名空间变量的命令行参数的主要内容,如果未能解决你的问题,请参考以下文章