简体   繁体   English

python cmd.Cmd 动态添加命令

[英]python cmd.Cmd dynamically add a command

I am trying to build a cli framework where commands need to be added to dynamically.我正在尝试构建一个 cli 框架,其中需要动态添加命令。 What I want to achieve is - I will have a minimum class which inherit from cmd.Cmd and later on I will write my commands in separate classes and load those commands along with main classes.我想要实现的是 - 我将有一个从 cmd.Cmd 继承的最小类,稍后我将在单独的类中编写我的命令并将这些命令与主类一起加载。

The following is what I tried but while trying to execute the command showmore, it throw TypeError以下是我尝试过但在尝试执行命令 showmore 时,它​​抛出 TypeError

import cmd

class MyExtraCmds(cmd.Cmd):

  def do_showmore(self, *args):
    print (type(self))
    print ("Show more command")

class MyCmd(cmd.Cmd):

  def __init__(self, target=None, user=None, passwd=None):
    cmd.Cmd.__init__(self)

  def do_show(self, *args):
    print (type(self))
    print ("Show command")

  def do_EOF(self, line):
    return True

if __name__ == "__main__":
    setattr(  MyCmd, 'do_showmore', MyExtraCmds.do_showmore)
    print (dir(MyCmd))
    target = MyCmd()
    target.cmdloop()

EDIT 2: I think you must be using Python 2, because in Python 3, this just works...编辑 2:我认为您必须使用 Python 2,因为在 Python 3 中,这只是有效...

MyExtrasCommand is a different class, so this won't work, because for a normal InstanceMethod, the first parameter must be an instance of the class. MyExtrasCommand 是一个不同的类,所以这不起作用,因为对于普通的 InstanceMethod,第一个参数必须是该类的实例。

But Python classes are open;但是 Python 类开放的; you can add to them later.您可以稍后添加它们。 The easiest thing to do is start off with methods that are not currently in a class, and then they will be properly added to the class at run-time.最简单的方法是从当前不在类中的方法开始,然后在运行时将它们正确添加到类中。 For example, this will work fine:例如,这将正常工作:

import cmd

def do_showmore(self, *args):
    print (type(self))
    print ("Show more command")

class MyCmd(cmd.Cmd):

    def __init__(self, target=None, user=None, passwd=None):
        cmd.Cmd.__init__(self)

    def do_show(self, *args):
        print (type(self))
        print ("Show command")

    def do_EOF(self, line):
        return True

if __name__ == "__main__":
    setattr(  MyCmd, 'do_showmore', do_showmore)
    print (dir(MyCmd))
    target = MyCmd()
    target.cmdloop()

If you print the type of MyCmd.do_showmore, you will see that your function has been properly wrapped into an InstanceMethod.如果您打印 MyCmd.do_showmore 的类型,您将看到您的函数已正确包装到一个 InstanceMethod 中。

EDIT (for information only -- you probably don't really want to do this...)编辑(仅供参考——你可能真的不想这样做......)

Since everything in Python is open and inspectable, you could make your initial approach work by changing a single line.由于 Python 中的所有内容都是开放且可检查的,因此您可以通过更改一行使您的初始方法起作用。 The following will work in Python 2.7:以下将在 Python 2.7 中工作:

setattr(  MyCmd, 'do_showmore', MyExtraCmds.do_showmore.im_func)

For Python 2.7, adding .im_func to the end of this line says "grab the underlying function from the MyExtraCmds.do_showmore unbound method and use it."对于 Python 2.7,将.im_func添加到这一行的末尾表示“从 MyExtraCmds.do_showmore 未绑定方法中获取底层函数并使用它。” I mention this because sometimes there are good reasons to use deep dark voodoo like this.我提到这一点是因为有时有充分的理由像这样使用深黑巫术。 But your described use-case doesn't seem like it would fit in here, and it could be very confusing if, for example, you added additional class variables to MyExtraCmds and expected do_showmore to be able to access them.但是您描述的用例似乎不适合这里,例如,如果您向MyExtraCmds添加了额外的类变量并期望do_showmore能够访问它们,则可能会非常混乱。 The function that you strip out of MyExtraCmds and add into MyCmd will no longer have any knowledge of MyExtraCmds so that would be misleading and confusing.您从MyExtraCmds并添加到MyCmd将不再了解MyExtraCmds因此会产生误导和混淆。

For me it works when I just set it with the equal operator.对我来说,当我用相等运算符设置它时它就起作用了。 It does work as a valid command.它确实作为一个有效的命令工作。

p = MyCmd()
p.do_extra = extra_command
p.cmdloop()

and I found a workaround to make it work for autocomplete and help.我找到了一种解决方法,使其适用于自动完成和帮助。 Reimplement get_names() in your class (I don't know why they used self. class instead of self there)重新实现get_names()在你的类(我不知道为什么他们用自己一流的,而不是自我存在)

class MyCmd(cmd.Cmd):
  def get_names(self):
    return dir(self)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM