cmd — 支持面向行的命令解释器 — Python 文档

来自菜鸟教程
Python/docs/3.8/library/cmd
跳转至:导航、​搜索

cmd — 支持面向行的命令解释器

源代码: :source:`Lib/cmd.py`



Cmd 类为编写面向行的命令解释器提供了一个简单的框架。 这些对于测试工具、管理工具和原型通常很有用,这些原型稍后将被包装在更复杂的界面中。

class cmd.Cmd(completekey='tab', stdin=None, stdout=None)

Cmd 实例或子类实例是面向行的解释器框架。 没有充分的理由实例化 Cmd 本身; 相反,它作为您自己定义的解释器类的超类很有用,以便继承 Cmd 的方法并封装操作方法。

可选参数 completekey 是完成键的 readline 名称; 它默认为 Tab。 如果 completekey 不是 None 并且 readline 可用,命令完成将自动完成。

可选参数 stdinstdout 指定 Cmd 实例或子类实例将用于输入和输出的输入和输出文件对象。 如果未指定,它们将默认为 sys.stdinsys.stdout

如果您想使用给定的 stdin,请确保将实例的 use_rawinput 属性设置为 False,否则 stdin 将被忽略。

命令对象

Cmd 实例具有以下方法:

Cmd.cmdloop(intro=None)

重复发出提示,接受输入,解析接收到的输入的初始前缀,然后分派到操作方法,将行的其余部分作为参数传递给它们。

可选参数是要在第一个提示之前发出的横幅或介绍字符串(这会覆盖 intro 类属性)。

如果加载了 readline 模块,输入将自动继承 bash-like history-list 编辑(例如 Control-P 回滚到上一个命令,Control-N 前进到下一个,Control-F 无损向右移动光标, Control-B 将光标非破坏性地向左移动,等等)。

输入的文件结尾作为字符串 'EOF' 传回。

当且仅当解释器实例具有方法 do_foo() 时,它才会识别命令名称 foo。 作为一种特殊情况,以字符 '?' 开头的行被分派给方法 do_help()。 作为另一种特殊情况,以字符 '!' 开头的行被分派给方法 do_shell()(如果定义了这样的方法)。

postcmd() 方法返回真值时,此方法将返回。 postcmd()stop 参数是命令对应的 do_*() 方法的返回值。

如果启用完成,则完成命令将自动完成,并且通过使用参数 textline、begidx[]调用 complete_foo() 完成命令 args X190X] 和 endidxtext 是我们试图匹配的字符串前缀:所有返回的匹配必须以它开头。 line 是当前输入行去掉前导空格,begidxendidx 是前缀文本的开始和结束索引,可以用来提供不同的完成取决于参数所在的位置。

Cmd 的所有子类都继承了一个预定义的 do_help()。 此方法使用参数 'bar' 调用,调用相应的方法 help_bar(),如果该方法不存在,则打印 do_bar() 的文档字符串(如果可用)。 没有参数,do_help() 列出所有可用的帮助主题(即所有具有相应 help_*() 方法的命令或具有文档字符串的命令),并列出所有未记录的命令。

Cmd.onecmd(str)
解释该参数,就好像它是为响应提示而键入的一样。 这可能会被覆盖,但通常不需要被覆盖; 有关有用的执行挂钩,请参阅 precmd()postcmd() 方法。 返回值是一个标志,指示解释器对命令的解释是否应该停止。 如果命令 strdo_*() 方法,则返回该方法的返回值,否则返回 default() 方法的返回值。
Cmd.emptyline()
当响应提示输入空行时调用的方法。 如果此方法未被覆盖,它会重复输入的最后一个非空命令。
Cmd.default(line)
无法识别命令前缀时在输入行上调用的方法。 如果此方法未被覆盖,它会打印一条错误消息并返回。
Cmd.completedefault(text, line, begidx, endidx)
当没有特定于命令的 complete_*() 方法可用时调用的方法来完成输入行。 默认情况下,它返回一个空列表。
Cmd.precmd(line)
Hook 方法在命令行 line 被解释之前执行,但在输入提示生成和发出之后执行。 这个方法是 Cmd 中的一个存根; 它的存在是为了被子类覆盖。 返回值用作将被onecmd()方法执行的命令; precmd() 实现可能会重写命令或简单地返回 line 不变。
Cmd.postcmd(stop, line)
命令分发完成后立即执行的钩子方法。 这个方法是 Cmd 中的一个存根; 它的存在是为了被子类覆盖。 line是被执行的命令行,stop是调用postcmd()后是否终止执行的标志; 这将是 onecmd() 方法的返回值。 此方法的返回值将用作对应于 stop 的内部标志的新值; 返回 false 将导致解释继续。
Cmd.preloop()
钩子方法在调用 cmdloop() 时执行一次。 这个方法是 Cmd 中的一个存根; 它的存在是为了被子类覆盖。
Cmd.postloop()
cmdloop() 即将返回时执行一次 Hook 方法。 这个方法是 Cmd 中的一个存根; 它的存在是为了被子类覆盖。

Cmd 子类的实例有一些公共实例变量:

Cmd.prompt
发出的提示请求输入。
Cmd.identchars
命令前缀接受的字符串。
Cmd.lastcmd
看到的最后一个非空命令前缀。
Cmd.cmdqueue
排队输入行的列表。 需要新输入时在cmdloop()中检查cmdqueue列表; 如果它是非空的,它的元素将被按顺序处理,就像在提示符下输入一样。
Cmd.intro
作为介绍或横幅发布的字符串。 可以通过给 cmdloop() 方法一个参数来覆盖。
Cmd.doc_header
如果帮助输出包含记录命令的部分,则要发出的标题。
Cmd.misc_header
如果帮助输出有一个用于其他帮助主题的部分(即,有 help_*() 方法没有相应的 do_*() 方法),则要发出的标题。
Cmd.undoc_header
如果帮助输出包含未记录命令的部分(即,有 do_*() 方法没有相应的 help_*() 方法),则要发出的标题。
Cmd.ruler
用于在帮助消息标题下绘制分隔线的字符。 如果为空,则不绘制标尺线。 默认为 '='
Cmd.use_rawinput
一个标志,默认为 true。 如果为 true,则 cmdloop() 使用 input() 显示提示并读取下一条命令; 如果为 false,则使用 sys.stdout.write()sys.stdin.readline()。 (这意味着通过导入 readline,在支持它的系统上,解释器将自动支持 Emacs 之类的行编辑和命令历史按键。)


命令示例

cmd 模块主要用于构建自定义 shell,让用户以交互方式使用程序。

本节提供了一个简单的示例,说明如何围绕 turtle 模块中的一些命令构建 shell。

基本的海龟命令如 forward() 被添加到 Cmd 子类中,方法名为 do_forward()。 参数被转换为一个数字并发送到海龟模块。 文档字符串在 shell 提供的帮助实用程序中使用。

该示例还包括使用 precmd() 方法实现的基本记录和回放工具,该方法负责将输入转换为小写并将命令写入文件。 do_playback()方法读取文件并将录制的命令添加到cmdqueue中进行即时回放:

import cmd, sys
from turtle import *

class TurtleShell(cmd.Cmd):
    intro = 'Welcome to the turtle shell.   Type help or ? to list commands.\n'
    prompt = '(turtle) '
    file = None

    # ----- basic turtle commands -----
    def do_forward(self, arg):
        'Move the turtle forward by the specified distance:  FORWARD 10'
        forward(*parse(arg))
    def do_right(self, arg):
        'Turn turtle right by given number of degrees:  RIGHT 20'
        right(*parse(arg))
    def do_left(self, arg):
        'Turn turtle left by given number of degrees:  LEFT 90'
        left(*parse(arg))
    def do_goto(self, arg):
        'Move turtle to an absolute position with changing orientation.  GOTO 100 200'
        goto(*parse(arg))
    def do_home(self, arg):
        'Return turtle to the home position:  HOME'
        home()
    def do_circle(self, arg):
        'Draw circle with given radius an options extent and steps:  CIRCLE 50'
        circle(*parse(arg))
    def do_position(self, arg):
        'Print the current turtle position:  POSITION'
        print('Current position is %d %d\n' % position())
    def do_heading(self, arg):
        'Print the current turtle heading in degrees:  HEADING'
        print('Current heading is %d\n' % (heading(),))
    def do_color(self, arg):
        'Set the color:  COLOR BLUE'
        color(arg.lower())
    def do_undo(self, arg):
        'Undo (repeatedly) the last turtle action(s):  UNDO'
    def do_reset(self, arg):
        'Clear the screen and return turtle to center:  RESET'
        reset()
    def do_bye(self, arg):
        'Stop recording, close the turtle window, and exit:  BYE'
        print('Thank you for using Turtle')
        self.close()
        bye()
        return True

    # ----- record and playback -----
    def do_record(self, arg):
        'Save future commands to filename:  RECORD rose.cmd'
        self.file = open(arg, 'w')
    def do_playback(self, arg):
        'Playback commands from a file:  PLAYBACK rose.cmd'
        self.close()
        with open(arg) as f:
            self.cmdqueue.extend(f.read().splitlines())
    def precmd(self, line):
        line = line.lower()
        if self.file and 'playback' not in line:
            print(line, file=self.file)
        return line
    def close(self):
        if self.file:
            self.file.close()
            self.file = None

def parse(arg):
    'Convert a series of zero or more numbers to an argument tuple'
    return tuple(map(int, arg.split()))

if __name__ == '__main__':
    TurtleShell().cmdloop()

这是一个使用乌龟壳的示例会话,显示了帮助功能,使用空行重复命令,以及简单的记录和回放功能:

Welcome to the turtle shell.   Type help or ? to list commands.

(turtle) ?

Documented commands (type help <topic>):
========================================
bye     color    goto     home  playback  record  right
circle  forward  heading  left  position  reset   undo

(turtle) help forward
Move the turtle forward by the specified distance:  FORWARD 10
(turtle) record spiral.cmd
(turtle) position
Current position is 0 0

(turtle) heading
Current heading is 0

(turtle) reset
(turtle) circle 20
(turtle) right 30
(turtle) circle 40
(turtle) right 30
(turtle) circle 60
(turtle) right 30
(turtle) circle 80
(turtle) right 30
(turtle) circle 100
(turtle) right 30
(turtle) circle 120
(turtle) right 30
(turtle) circle 120
(turtle) heading
Current heading is 180

(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 500
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 300
(turtle) playback spiral.cmd
Current position is 0 0

Current heading is 0

Current heading is 180

(turtle) bye
Thank you for using Turtle