【问题标题】:Python cmd module - parsing values from linePython cmd模块 - 从行解析值
【发布时间】:2012-04-19 18:36:47
【问题描述】:

我正在使用cmd 模块编写一个快速python 脚本,该模块将允许用户输入文本命令,后跟基本url 查询字符串格式的参数。提示将得到类似

的回答

commandname foo=bar&baz=brack

使用 cmd,我似乎找不到要覆盖哪个方法来影响参数 line 被传递给所有 do_* 方法的方式。我想在这些值上运行urlparse.parse_qs,并在每个do_* 方法中逐行调用它似乎很笨拙。

precmd 方法在 commandname 被拆分和解释之前获取整行,因此这不适用于我的目的。我也不太熟悉如何在这样的类中放置装饰器,并且无法在不破坏范围的情况下将其拉下来。

基本上,cmd 的 python 文档会说以下内容

反复发出提示,接受输入,解析初始前缀关闭 接收到的输入,并分派给动作方法,将它们传递给 该行的其余部分作为参数。

我想创建一个方法,对该“行的剩余部分”进行额外处理,并将生成的字典作为 line 参数传递给成员函数,而不是在每个函数中解释它们。

谢谢!

【问题讨论】:

    标签: python cmd command-line-interface


    【解决方案1】:

    您可能会覆盖onecmd() 方法,如下面的快速示例所示。 onecmd() 方法基本上是原始 cmd.py 的一个副本,但在将参数传递给函数之前添加了对 urlparse.parse_qs() 的调用。

    import cmd
    import urlparse
    
    class myCmd(cmd.Cmd):
        def onecmd(self, line):
            """Mostly ripped from Python's cmd.py"""
            cmd, arg, line = self.parseline(line)
            arg = urlparse.parse_qs(arg) # <- added line
            if not line:
                return self.emptyline()
            if cmd is None:
                return self.default(line)
            self.lastcmd = line
            if cmd == '':
                return self.default(line)
            else:
                try:
                    func = getattr(self, 'do_' + cmd)
                except AttributeError:
                    return self.default(line)
                return func(arg)
    
        def do_foo(self, arg)
            print arg
    
    my_cmd = myCmd()
    my_cmd.cmdloop()
    

    样本输出:

    (Cmd) foo
    {}
    (Cmd) foo a b c
    {}
    (Cmd) foo a=b&c=d
    {'a': ['b'], 'c': ['d']}
    

    这是你想要达到的目标吗?

    这是另一个潜在的解决方案,它使用类装饰器来修改 cmd.Cmd 子类并基本上将装饰器功能应用于所有 do_* 该类的方法:

    import cmd
    import urlparse
    import types
    
    # function decorator to add parse_qs to individual functions
    def parse_qs_f(f):
        def f2(self, arg):
            return f(self, urlparse.parse_qs(arg))
        return f2
    
    # class decorator to iterate over all attributes of a class and apply
    # the parse_qs_f decorator to all do_* methods
    def parse_qs(cls):
        for attr_name in dir(cls):
            attr = getattr(cls, attr_name)
            if attr_name.startswith('do_') and type(attr) == types.MethodType:
                setattr(cls, attr_name, parse_qs_f(attr))
        return cls
    
    @parse_qs
    class myCmd(cmd.Cmd):
        def do_foo(self, args):
            print args
    
    my_cmd = myCmd()
    my_cmd.cmdloop()
    

    我很快把它拼凑起来,它似乎按预期工作,但是,我 欢迎就任何陷阱或如何改进此解决方案提出建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-10
      • 2018-10-17
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      相关资源
      最近更新 更多