离线下载
PDF版 ePub版

qyuhen · 更新于 2018-11-28 11:00:43

程序框架

cmd

可用 cmd 写出 mongo、redis-cli 那样的交互命令行客户端。支持常用快捷键和命令补全提示。

从 Cmd 继承,然后按需要重写相关的方法。比较郁闷的是 Cmd 是 Classic Class,建议用多继承加个 object 基类,否则无法使用 super 调用基类方法。

preloop
cmdloop
    precmd  修正命令信息,返回 line。
    onecmd  查找并执行 do_* 方法。  返回 stop 给 postcmd。
        do_*  比如 test 命令,对应 do_test。 返回 stop 给 onecmd。
        default  没找到 do_* 或无法解析的命令,默认显示错误提示。
        emptyline 不输入命令,直接回车。默认重复上次命名。

        do_shell  调用系统命令。
        complete_* 参数补全。如果没有对应方法,默认调用 completedefault。

        help_*  help cmd 或  cmd 显示具体命令帮助信息 (__doc__)。
        do_help help 默认显示全部命令列表,可重写本方法修改输出。
    postcmd  接收 stop 参数,返回 True 终止 cmdloop 循环。
postloop

通过返回 stop 值决定是否继续 cmdloop 循环。好在函数默认返回 None,没必要显式 return。参数 line 不包括命令串。

相关属性:

prompt   命令提示符。
identchars   有效命令字符,默认是数字、字母和下划线。
lastcmd   最后一条命令。
intro    介绍。
doc_header   命令帮助标题。
misc_header   没找到帮助时显示的标题。
undoc_header   没有 __doc__ 时显示的标题。
ruler    帮助信息分隔线,默认 "="。
use_rawinput   默认 True。

示例:

#/usr/bin/env python
#coding=utf-8

from os import popen
from cmd import Cmd
from shlex import split as shsplit

class Shell(Cmd, object):
    intro = "TEST shell, version 0.0.0.1"
    prompt = "$ "

    def default(self, line):
        # 退出 (EOF, <ctrl> + d)
        if line in ("exit", "quit", "bye", "EOF"):
            print "bye..."
            return True

        # 未知命令
        super(Shell, self).default(line)

    def do_test(self, line):
        # 参数分割
        print shsplit(line)
    def complete_test(self, text, line, beginidx, endidx):
        # 参数补全
        args = ("a1", "a2", "b1", "b2")
        return args if not text else filter(lambda s: s.startswith(text), args)

    def do_shell(self, line):
        # 系统命令
        print popen(line).read()
if __name__ == "__main__":
    Shell().cmdloop()

还可以用 code.interact() 嵌入 Python Shell 交互环境。

shlex

shlex 是一个分割 Unix Shell 命令行参数的简单词法分析器。

>>> from shlex import split
>>> split("ls -l /usr/local")
['ls', '-l', '/usr/local']

>>> split('test a b "c d"')  # 对引号参数的支持
['test', 'a', 'b', 'c d']

如果要将分解的列表还原,可以用 subprocess.list2cmdline。

>>> from subprocess import list2cmdline

>>> args = split('test a b "c d"')

>>> list2cmdline(args)
'test a b "c d"'

复杂的参数处理,应该使用 argparse。

上一篇: 进程通信 下一篇: 第三部分 扩展库