多个未标记参数与水泥一起使用

7 投票
2 回答
1322 浏览
提问于 2025-04-18 10:56

我正在用 cement 写一个 Python 命令行工具。Cement 在处理标准参数解析方面表现得很好。不过,我想添加一些没有标志的特定参数。让我来解释一下。

典型的命令行工具是这样的:

cmd subcmd -flag -stored=flag

现在,假设我想添加一些没有标志的参数,比如说像 cd 命令那样。

cd my/dir

my/dir 是一个没有标志的参数。

有没有办法用 cement 实现这个功能呢?

这是我目前的 cement 应用示例:

# define application controllers
class MyAppBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        interface = controller.IController
        description = "My Application Does Amazing Things"
        arguments = [
            (['--base-opt'], dict(help="option under base controller")),
            ]

    @controller.expose(help="base controller default command", hide=True)
    def default(self):
        self.app.args.parse_args(['--help'])
        print "Inside MyAppBaseController.default()"

    @controller.expose(help="another base controller command")
    def command1(self):
        print "Inside MyAppBaseController.command1()"

假设我想执行 myapp command1 some/dir some_string

有没有办法解析这些参数呢?

2 个回答

1

在Cement的文档中提到:“Cement定义了一个叫做IArgument的参数接口,还有一个默认的ArgParseArgumentHandler来实现这个接口。这个处理器是基于Python标准库中的ArgParse模块构建的。”

你可以通过告诉argparse模块,从参数列表中获取一个参数,并把它存储在pargs列表的name属性中来实现这个功能。

# define application controllers
class MyAppBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        interface = controller.IController
        description = "My Application Does Amazing Things"
        arguments = [
            (['--base-opt'], dict(help="option under base controller")),
        ]

    @controller.expose(help="base controller default command", hide=True)
    def default(self):
        self.app.args.parse_args(['--help'])
        print "Inside MyAppBaseController.default()"

    @controller.expose(
        help="another base controller command",
        arguments=[
            (['path'],
             dict(type=str, metavar='PATH', nargs='?', action='store', default='.')),
            (['string'],
             dict(type=str, metavar='STRING', nargs='?', action='store', default='')),
        ]
    )
    def command1(self):
        print "Inside MyAppBaseController.command1() path: %s string: %s" % (self.app.pargs.name, self.app.pargs.string)
13

你可以通过在ArgParse中使用可选的位置参数来实现这个功能。实际上,GitHub上有一个关于这个主题的文档改进问题:

https://github.com/datafolklabs/cement/issues/256

简单来说,如果你想让“command1”来处理某个操作,那么“some/dir some_string”就是位置参数。你可以在MyAppBaseController.Meta.arguments中添加以下内容:

( ['extra_arguments'], dict(action='store', nargs='*') ),

然后在command函数内部这样访问这些参数:

if self.app.pargs.extra_arguments: print "额外参数 0: %s" % self.app.pargs.extra_arguments[0] print "额外参数 1: %s" % self.app.pargs.extra_arguments[1]

撰写回答