[英]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.