如何构建一个具有独立命令模块的Python命令行应用程序

2 投票
1 回答
817 浏览
提问于 2025-04-16 19:31

我正在用cmd2模块写一个Python命令行工具,这个模块是cmd的升级版。这个工具是一个管理应用程序,用来管理多个子模块。

我想把代码结构设计成每个子模块都有自己的类,负责提供可以在该模块上执行的命令。但我不太确定该怎么组织这些代码,因为命令类的工作方式让我有些困惑。

所以我想要的结构大概是这样的:

import cmd

class ConsoleApp(cmd.Cmd):

    # this is the main app and should get the commands from the sub-modules

app = ConsoleApp()
app.cmdloop()

然后这些子模块会被单独定义。

class SubModuleA():

    def do_sm_a_command_1(self, line):
        print "sm a command 1"

class SubModuleB():

    def do_sm_b_command_1(self, line):
        print "sm b command 2"

我该如何组织这些代码,让主应用能够获取子模块中的命令呢?

谢谢,Jon

1 个回答

1

你可以尝试把你的子模块(SubModules)设计成主控制台应用(ConsoleApp)的插件。这样的话,你需要在控制台应用里添加几个新方法。比如,可以有一个叫 add_command_module(self, klass) 的方法,这个方法的作用就是把子模块(比如 SubModuleA)添加到控制台应用内部的一个列表里。

接着,在控制台应用中,你需要重写 onecmd 这个方法,让它看起来像下面这样:

def onecmd(self, 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:
    # iterate over all submodules that have been added including ourselves
    # self.submodules would just be a list or set of all submodules as mentioned above
    func = None
    for submod in self.submodules:
      # just return the first match we find
      if hasattr(submod, 'do_%s' % cmd):
        func = getattr(submod, 'do_%s' % cmd)
        break # instead of breaking, you could also add up all the modules that have
              # this method, and tell the user to be more specific
    if func is not None:
      return func(arg)
    else:
      return self.default(line)

你还可以对 parseline 方法进行一些修改,让它能够识别命令的子模块前缀等等……

撰写回答