使用 Python 的 `argh` 时如何收集未指定的命令行选项?
How can I collect unspecified command line options when using Python's `argh`?
使用 Python CLI 库 argh
我想编写一个包装器工具。这个包装器工具假设读取两个选项 -a
和 -b
并将所有其他选项传递给一个函数(然后通过 subprocess
使用剩余选项调用包装的 UNIX 工具).
我已经试验过 dispatch
的参数 skip_unknown_args
:
def wrapper(a=True, b=False):
print("Enter wrapper")
# 1. process a and b
# 2. call_unix_tool(left-over-args)
if __name__ == '__main__':
parser = argh.ArghParser()
argh.set_default_command(parser, wrapper)
argh.dispatch(parser, skip_unknown_args=True)
但是程序在遇到未知选项时仍然退出,并没有按需要进入函数wrapper
。此外,我不知道 unknown/skipped 参数存储在哪里,以便我可以将它们传递给 UNIX 工具。
如何让 argh
使用跳过的参数进入 wrapper
?
我认为这是一个错误。
当skip_unknown_args=True
时,这里namespace_obj
是一个元组,有一个命名空间对象和剩余的参数:
(Pdb) p namespace_obj
(ArghNamespace(_functions_stack=[<function wrapper at 0x105cb5e18>], a=False, b=True), ['-c'])
底层 _get_function_from_namespace_obj
需要一元:
154 function = _get_function_from_namespace_obj(namespace_obj)
...
191 if isinstance(namespace_obj, ArghNamespace):
我检查了its coressponding issue and unittest,不知道作者期望的合法行为是什么,也在那里发表了评论。
为什么不直接使用argparse
?
您不能使用 skip_unknown_args=True
执行此操作,因为 argh
库在使用该选项时似乎表现不佳。但是,您可以提供自己的解析器 class,它将未知参数注入普通命名空间:
class ArghParserWithUnknownArgs(argh.ArghParser):
def parse_args(self, args=None, namespace=None):
namespace = namespace or ArghNamespace()
(namespace_obj, unknown_args) = super(ArghParserWithUnknownArgs, self).parse_known_args(args=args, namespace=namespace)
namespace_obj.__dict__['unknown_args'] = unknown_args
return namespace_obj
请注意,此 class' parse_args
方法调用 ArgParser
的 parse_
known
_args
方法!
有了这个 class 定义,您可以按照以下方式编写包装代码:
def wrapper(a=True, b=False, unknown_args={}):
print("a = %s, b = %s" % (a,b))
print("unknown_args = %s" % unknown_args)
if __name__ == '__main__':
parser = ArghParserWithUnknownArgs()
argh.set_default_command(parser, wrapper)
argh.dispatch(parser)
在您的主函数 wrapper
中,您可以通过参数 unknown_args
访问所有未知参数,并将其传递给您的子进程命令
ps:为了保持帮助信息的整洁,用
修饰wrapper
@argh.arg('--unknown_args', help=argparse.SUPPRESS)
附录:我创建了一个增强版的解析器并将其编译成一个随时可用的模块。在 Github.
上找到它
使用 Python CLI 库 argh
我想编写一个包装器工具。这个包装器工具假设读取两个选项 -a
和 -b
并将所有其他选项传递给一个函数(然后通过 subprocess
使用剩余选项调用包装的 UNIX 工具).
我已经试验过 dispatch
的参数 skip_unknown_args
:
def wrapper(a=True, b=False):
print("Enter wrapper")
# 1. process a and b
# 2. call_unix_tool(left-over-args)
if __name__ == '__main__':
parser = argh.ArghParser()
argh.set_default_command(parser, wrapper)
argh.dispatch(parser, skip_unknown_args=True)
但是程序在遇到未知选项时仍然退出,并没有按需要进入函数wrapper
。此外,我不知道 unknown/skipped 参数存储在哪里,以便我可以将它们传递给 UNIX 工具。
如何让 argh
使用跳过的参数进入 wrapper
?
我认为这是一个错误。
当skip_unknown_args=True
时,这里namespace_obj
是一个元组,有一个命名空间对象和剩余的参数:
(Pdb) p namespace_obj
(ArghNamespace(_functions_stack=[<function wrapper at 0x105cb5e18>], a=False, b=True), ['-c'])
底层 _get_function_from_namespace_obj
需要一元:
154 function = _get_function_from_namespace_obj(namespace_obj)
...
191 if isinstance(namespace_obj, ArghNamespace):
我检查了its coressponding issue and unittest,不知道作者期望的合法行为是什么,也在那里发表了评论。
为什么不直接使用argparse
?
您不能使用 skip_unknown_args=True
执行此操作,因为 argh
库在使用该选项时似乎表现不佳。但是,您可以提供自己的解析器 class,它将未知参数注入普通命名空间:
class ArghParserWithUnknownArgs(argh.ArghParser):
def parse_args(self, args=None, namespace=None):
namespace = namespace or ArghNamespace()
(namespace_obj, unknown_args) = super(ArghParserWithUnknownArgs, self).parse_known_args(args=args, namespace=namespace)
namespace_obj.__dict__['unknown_args'] = unknown_args
return namespace_obj
请注意,此 class' parse_args
方法调用 ArgParser
的 parse_
known
_args
方法!
有了这个 class 定义,您可以按照以下方式编写包装代码:
def wrapper(a=True, b=False, unknown_args={}):
print("a = %s, b = %s" % (a,b))
print("unknown_args = %s" % unknown_args)
if __name__ == '__main__':
parser = ArghParserWithUnknownArgs()
argh.set_default_command(parser, wrapper)
argh.dispatch(parser)
在您的主函数 wrapper
中,您可以通过参数 unknown_args
访问所有未知参数,并将其传递给您的子进程命令
ps:为了保持帮助信息的整洁,用
修饰wrapper
@argh.arg('--unknown_args', help=argparse.SUPPRESS)
附录:我创建了一个增强版的解析器并将其编译成一个随时可用的模块。在 Github.
上找到它