2019-04-21 11:50:48 +08:00

131 lines
35 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-cmd"><h1><span class="yiyi-st" id="yiyi-10">24.2。 <a class="reference internal" href="#module-cmd" title="cmd: Build line-oriented command interpreters."><code class="xref py py-mod docutils literal"><span class="pre">cmd</span></code></a> - 支持面向行的命令解释器</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/cmd.py">Lib / cmd.py</a></span></p><p><span class="yiyi-st" id="yiyi-12"><a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>类提供了一个用于编写面向行的命令解释器的简单框架。</span><span class="yiyi-st" id="yiyi-13">这些对于测试套件,管理工具和原型通常是有用的,它们将被包装在更复杂的界面中。</span></p><dl class="class"><dt id="cmd.Cmd"><span class="yiyi-st" id="yiyi-14"> <em class="property">class </em><code class="descclassname">cmd.</code><code class="descname">Cmd</code><span class="sig-paren">(</span><em>completekey='tab'</em>, <em>stdin=None</em>, <em>stdout=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-15">A <a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>实例或子类实例是一个面向行的解释器框架。</span><span class="yiyi-st" id="yiyi-16">没有好的理由实例化<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>本身;相反,它作为您定义的解释器类的超类是有用的,以便继承<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>的方法并封装动作方法。</span></p><p><span class="yiyi-st" id="yiyi-17">可选参数<em>completekey</em>是完成键的<a class="reference internal" href="readline.html#module-readline" title="readline: GNU readline support for Python. (Unix)"><code class="xref py py-mod docutils literal"><span class="pre">readline</span></code></a>名称;它默认为<code class="kbd docutils literal"><span class="pre">Tab</span></code></span><span class="yiyi-st" id="yiyi-18">如果<em>completekey</em>不是<a class="reference internal" href="constants.html#None" title="None"><code class="xref py py-const docutils literal"><span class="pre">None</span></code></a><a class="reference internal" href="readline.html#module-readline" title="readline: GNU readline support for Python. (Unix)"><code class="xref py py-mod docutils literal"><span class="pre">readline</span></code></a>可用,则命令完成自动完成。</span></p><p><span class="yiyi-st" id="yiyi-19">可选参数<em>stdin</em><em>stdout</em>指定Cmd实例或子类实例将用于输入和输出的输入和输出文件对象。</span><span class="yiyi-st" id="yiyi-20">如果未指定,它们将默认为<a class="reference internal" href="sys.html#sys.stdin" title="sys.stdin"><code class="xref py py-data docutils literal"><span class="pre">sys.stdin</span></code></a><a class="reference internal" href="sys.html#sys.stdout" title="sys.stdout"><code class="xref py py-data docutils literal"><span class="pre">sys.stdout</span></code></a></span></p><p><span class="yiyi-st" id="yiyi-21">如果要使用给定的<em>stdin</em>,请确保将实例的<a class="reference internal" href="#cmd.Cmd.use_rawinput" title="cmd.Cmd.use_rawinput"><code class="xref py py-attr docutils literal"><span class="pre">use_rawinput</span></code></a>属性设置为<code class="docutils literal"><span class="pre">False</span></code>,否则<em>stdin 将被忽略。</em></span></p></dd></dl><div class="section" id="cmd-objects"><h2><span class="yiyi-st" id="yiyi-22">24.2.1. </span><span class="yiyi-st" id="yiyi-23">Cmd对象</span></h2><p><span class="yiyi-st" id="yiyi-24">A <a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>实例具有以下方法:</span></p><dl class="method"><dt id="cmd.Cmd.cmdloop"><span class="yiyi-st" id="yiyi-25"> <code class="descclassname">Cmd.</code><code class="descname">cmdloop</code><span class="sig-paren">(</span><em>intro=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-26">重复发出提示,接受输入,解析接收到的输入的初始前缀,并分派到动作方法,将其余行作为参数传递。</span></p><p><span class="yiyi-st" id="yiyi-27">可选参数是在第一个提示之前发出的横幅或介绍字符串(这将覆盖<a class="reference internal" href="#cmd.Cmd.intro" title="cmd.Cmd.intro"><code class="xref py py-attr docutils literal"><span class="pre">intro</span></code></a>类属性)。</span></p><p><span class="yiyi-st" id="yiyi-28">如果加载了<a class="reference internal" href="readline.html#module-readline" title="readline: GNU readline support for Python. (Unix)"><code class="xref py py-mod docutils literal"><span class="pre">readline</span></code></a>模块,则输入将自动继承<strong class="program">bash</strong>样历史列表编辑(例如,</span><span class="yiyi-st" id="yiyi-29"><code class="kbd docutils literal"><span class="pre">Control-P</span></code>滚动返回到最后一个命令,<code class="kbd docutils literal"><span class="pre">Control-N</span></code>转到下一个命令,<code class="kbd docutils literal"><span class="pre">Control-F</span></code> - 破坏性地,<code class="kbd docutils literal"><span class="pre">Control-B</span></code>非破坏性地将光标向左移动等。</span><span class="yiyi-st" id="yiyi-30">)。</span></p><p><span class="yiyi-st" id="yiyi-31">输入上的文件结尾以字符串<code class="docutils literal"><span class="pre">'EOF'</span></code>返回。</span></p><p><span class="yiyi-st" id="yiyi-32">当且仅当它具有方法<code class="xref py py-meth docutils literal"><span class="pre">do_foo()</span></code>时,解释器实例将识别命令名<code class="docutils literal"><span class="pre">foo</span></code></span><span class="yiyi-st" id="yiyi-33">作为特殊情况,以字符<code class="docutils literal"><span class="pre">'?'</span></code>开头的行</span><span class="yiyi-st" id="yiyi-34">被分派到方法<code class="xref py py-meth docutils literal"><span class="pre">do_help()</span></code></span><span class="yiyi-st" id="yiyi-35">作为另一种特殊情况,以字符<code class="docutils literal"><span class="pre">'!'</span></code>开头的行</span><span class="yiyi-st" id="yiyi-36">被分派到方法<code class="xref py py-meth docutils literal"><span class="pre">do_shell()</span></code>(如果定义了这样的方法)。</span></p><p><span class="yiyi-st" id="yiyi-37"><a class="reference internal" href="#cmd.Cmd.postcmd" title="cmd.Cmd.postcmd"><code class="xref py py-meth docutils literal"><span class="pre">postcmd()</span></code></a>方法返回true值时此方法将返回。</span><span class="yiyi-st" id="yiyi-38"><a class="reference internal" href="#cmd.Cmd.postcmd" title="cmd.Cmd.postcmd"><code class="xref py py-meth docutils literal"><span class="pre">postcmd()</span></code></a><em>stop</em>参数是命令的相应<code class="xref py py-meth docutils literal"><span class="pre">do_*()</span></code>方法的返回值。</span></p><p><span class="yiyi-st" id="yiyi-39">如果启用完成,则将自动完成命令,并且通过使用参数<em>文本</em><em></em>调用<code class="xref py py-meth docutils literal"><span class="pre">complete_foo()</span></code>完成命令args <em>begidx</em><em>endidx</em></span><span class="yiyi-st" id="yiyi-40"><em>text</em>是我们尝试匹配的字符串前缀:所有返回的匹配都必须以它开头。</span><span class="yiyi-st" id="yiyi-41"><em></em>是移除了前导空白的当前输入行,<em>begidx</em><em>endidx</em>是前缀文本的开始和结束索引,以根据参数在哪个位置提供不同的完成。</span></p><p><span class="yiyi-st" id="yiyi-42"><a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>的所有子类继承预定义的<code class="xref py py-meth docutils literal"><span class="pre">do_help()</span></code></span><span class="yiyi-st" id="yiyi-43">这个方法用参数<code class="docutils literal"><span class="pre">'bar'</span></code>调用,调用相应的方法<code class="xref py py-meth docutils literal"><span class="pre">help_bar()</span></code>,如果不存在,打印<code class="xref py py-meth docutils literal"><span class="pre">do_bar()</span></code>(如果可用)。</span><span class="yiyi-st" id="yiyi-44">没有参数,<code class="xref py py-meth docutils literal"><span class="pre">do_help()</span></code>列出所有可用的帮助主题(即,所有命令与相应的<code class="xref py py-meth docutils literal"><span class="pre">help_*()</span></code>方法或具有docstrings的命令未记录的命令。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.onecmd"><span class="yiyi-st" id="yiyi-45"> <code class="descclassname">Cmd.</code><code class="descname">onecmd</code><span class="sig-paren">(</span><em>str</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-46">解释参数,就像它已经响应提示输入。</span><span class="yiyi-st" id="yiyi-47">这可能被覆盖,但通常不需要;请参阅有用的执行钩子的<a class="reference internal" href="#cmd.Cmd.precmd" title="cmd.Cmd.precmd"><code class="xref py py-meth docutils literal"><span class="pre">precmd()</span></code></a><a class="reference internal" href="#cmd.Cmd.postcmd" title="cmd.Cmd.postcmd"><code class="xref py py-meth docutils literal"><span class="pre">postcmd()</span></code></a>方法。</span><span class="yiyi-st" id="yiyi-48">返回值是指示解释器对命令的解释是否应该停止的标志。</span><span class="yiyi-st" id="yiyi-49">如果命令<em>str</em><code class="xref py py-meth docutils literal"><span class="pre">do_*()</span></code>方法,则返回该方法的返回值,否则返回<a class="reference internal" href="#cmd.Cmd.default" title="cmd.Cmd.default"><code class="xref py py-meth docutils literal"><span class="pre">default()</span></code></a></span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.emptyline"><span class="yiyi-st" id="yiyi-50"> <code class="descclassname">Cmd.</code><code class="descname">emptyline</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-51">响应提示输入空行时调用的方法。</span><span class="yiyi-st" id="yiyi-52">如果此方法未被覆盖,它将重复输入的最后一个非空命令。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.default"><span class="yiyi-st" id="yiyi-53"> <code class="descclassname">Cmd.</code><code class="descname">default</code><span class="sig-paren">(</span><em>line</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-54">无法识别命令前缀时在输入行上调用的方法。</span><span class="yiyi-st" id="yiyi-55">如果此方法未覆盖,它将输出错误消息并返回。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.completedefault"><span class="yiyi-st" id="yiyi-56"> <code class="descclassname">Cmd.</code><code class="descname">completedefault</code><span class="sig-paren">(</span><em>text</em>, <em>line</em>, <em>begidx</em>, <em>endidx</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-57">当没有特定于命令的<code class="xref py py-meth docutils literal"><span class="pre">complete_*()</span></code>方法可用时,调用完成输入行的方法。</span><span class="yiyi-st" id="yiyi-58">默认情况下,它返回一个空列表。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.precmd"><span class="yiyi-st" id="yiyi-59"> <code class="descclassname">Cmd.</code><code class="descname">precmd</code><span class="sig-paren">(</span><em>line</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-60">在命令行<em></em>之前执行的Hook方法被解释但是在生成并发出输入提示之后。</span><span class="yiyi-st" id="yiyi-61">此方法是<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>中的存根;它存在被子类覆盖。</span><span class="yiyi-st" id="yiyi-62">返回值用作将由<a class="reference internal" href="#cmd.Cmd.onecmd" title="cmd.Cmd.onecmd"><code class="xref py py-meth docutils literal"><span class="pre">onecmd()</span></code></a>方法执行的命令; <a class="reference internal" href="#cmd.Cmd.precmd" title="cmd.Cmd.precmd"><code class="xref py py-meth docutils literal"><span class="pre">precmd()</span></code></a>实现可以重写命令或简单地返回<em></em>而不改变。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.postcmd"><span class="yiyi-st" id="yiyi-63"> <code class="descclassname">Cmd.</code><code class="descname">postcmd</code><span class="sig-paren">(</span><em>stop</em>, <em>line</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-64">在命令分派完成后执行Hook方法。</span><span class="yiyi-st" id="yiyi-65">此方法是<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>中的存根;它存在被子类覆盖。</span><span class="yiyi-st" id="yiyi-66"><em></em>是被执行的命令行,<em>停止</em>是指示在调用<a class="reference internal" href="#cmd.Cmd.postcmd" title="cmd.Cmd.postcmd"><code class="xref py py-meth docutils literal"><span class="pre">postcmd()</span></code></a>后是否终止执行的标志;这将是<a class="reference internal" href="#cmd.Cmd.onecmd" title="cmd.Cmd.onecmd"><code class="xref py py-meth docutils literal"><span class="pre">onecmd()</span></code></a>方法的返回值。</span><span class="yiyi-st" id="yiyi-67">此方法的返回值将用作对应于<em>stop</em>的内部标志的新值返回false将导致解释继续。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.preloop"><span class="yiyi-st" id="yiyi-68"> <code class="descclassname">Cmd.</code><code class="descname">preloop</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-69">当调用<a class="reference internal" href="#cmd.Cmd.cmdloop" title="cmd.Cmd.cmdloop"><code class="xref py py-meth docutils literal"><span class="pre">cmdloop()</span></code></a>时执行一次Hook方法。</span><span class="yiyi-st" id="yiyi-70">此方法是<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>中的存根;它存在被子类覆盖。</span></p></dd></dl><dl class="method"><dt id="cmd.Cmd.postloop"><span class="yiyi-st" id="yiyi-71"> <code class="descclassname">Cmd.</code><code class="descname">postloop</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-72"><a class="reference internal" href="#cmd.Cmd.cmdloop" title="cmd.Cmd.cmdloop"><code class="xref py py-meth docutils literal"><span class="pre">cmdloop()</span></code></a>即将返回时执行一次Hook方法。</span><span class="yiyi-st" id="yiyi-73">此方法是<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>中的存根;它存在被子类覆盖。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-74"><a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>子类的实例有一些公共实例变量:</span></p><dl class="attribute"><dt id="cmd.Cmd.prompt"><span class="yiyi-st" id="yiyi-75"> <code class="descclassname">Cmd.</code><code class="descname">prompt</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-76">发出提示以征求输入。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.identchars"><span class="yiyi-st" id="yiyi-77"> <code class="descclassname">Cmd.</code><code class="descname">identchars</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-78">命令前缀接受的字符串字符串。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.lastcmd"><span class="yiyi-st" id="yiyi-79"> <code class="descclassname">Cmd.</code><code class="descname">lastcmd</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-80">显示的最后一个非空命令前缀。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.cmdqueue"><span class="yiyi-st" id="yiyi-81"> <code class="descclassname">Cmd.</code><code class="descname">cmdqueue</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-82">队列输入行的列表。</span><span class="yiyi-st" id="yiyi-83">当需要新输入时,在<a class="reference internal" href="#cmd.Cmd.cmdloop" title="cmd.Cmd.cmdloop"><code class="xref py py-meth docutils literal"><span class="pre">cmdloop()</span></code></a>中检查cmdqueue列表如果它是非空的其元素将按顺序处理如同在提示符处输入。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.intro"><span class="yiyi-st" id="yiyi-84"> <code class="descclassname">Cmd.</code><code class="descname">intro</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-85">要作为简介或横幅发出的字符串。</span><span class="yiyi-st" id="yiyi-86">可以通过将<a class="reference internal" href="#cmd.Cmd.cmdloop" title="cmd.Cmd.cmdloop"><code class="xref py py-meth docutils literal"><span class="pre">cmdloop()</span></code></a>方法作为参数来覆盖。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.doc_header"><span class="yiyi-st" id="yiyi-87"> <code class="descclassname">Cmd.</code><code class="descname">doc_header</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-88">如果帮助输出具有已记录命令的部分,则发出标题。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.misc_header"><span class="yiyi-st" id="yiyi-89"> <code class="descclassname">Cmd.</code><code class="descname">misc_header</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-90">如果帮助输出具有其他帮助主题的部分(即,没有对应的<code class="xref py py-meth docutils literal"><span class="pre">do_*()</span></code>方法的<code class="xref py py-meth docutils literal"><span class="pre">help_*()</span></code>方法),则发出标题。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.undoc_header"><span class="yiyi-st" id="yiyi-91"> <code class="descclassname">Cmd.</code><code class="descname">undoc_header</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-92">如果帮助输出具有未记录的命令的部分(即,没有相应的<code class="xref py py-meth docutils literal"><span class="pre">help_*()</span></code>方法的<code class="xref py py-meth docutils literal"><span class="pre">do_*()</span></code>方法),则发出标题。</span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.ruler"><span class="yiyi-st" id="yiyi-93"> <code class="descclassname">Cmd.</code><code class="descname">ruler</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-94">用于在帮助消息标题下绘制分隔线的字符。</span><span class="yiyi-st" id="yiyi-95">如果为空,则不绘制标尺线。</span><span class="yiyi-st" id="yiyi-96">它默认为<code class="docutils literal"><span class="pre">'='</span></code></span></p></dd></dl><dl class="attribute"><dt id="cmd.Cmd.use_rawinput"><span class="yiyi-st" id="yiyi-97"> <code class="descclassname">Cmd.</code><code class="descname">use_rawinput</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-98">一个标志默认为true。</span><span class="yiyi-st" id="yiyi-99">如果为true<a class="reference internal" href="#cmd.Cmd.cmdloop" title="cmd.Cmd.cmdloop"><code class="xref py py-meth docutils literal"><span class="pre">cmdloop()</span></code></a>使用<a class="reference internal" href="functions.html#input" title="input"><code class="xref py py-func docutils literal"><span class="pre">input()</span></code></a>显示提示并读取下一个命令如果为false则使用<code class="xref py py-meth docutils literal"><span class="pre">sys.stdout.write()</span></code><code class="xref py py-meth docutils literal"><span class="pre">sys.stdin.readline()</span></code></span><span class="yiyi-st" id="yiyi-100">(这意味着通过导入<a class="reference internal" href="readline.html#module-readline" title="readline: GNU readline support for Python. (Unix)"><code class="xref py py-mod docutils literal"><span class="pre">readline</span></code></a>,在支持它的系统上,解释器将自动支持<strong class="program">Emacs</strong> - 例如行编辑和命令历史击键。</span></p></dd></dl></div><div class="section" id="cmd-example"><h2><span class="yiyi-st" id="yiyi-101">24.2.2. </span><span class="yiyi-st" id="yiyi-102">Cmd示例</span></h2><p><span class="yiyi-st" id="yiyi-103"><a class="reference internal" href="#module-cmd" title="cmd: Build line-oriented command interpreters."><code class="xref py py-mod docutils literal"><span class="pre">cmd</span></code></a>模块主要用于构建允许用户以交互方式处理程序的自定义外壳。</span></p><p><span class="yiyi-st" id="yiyi-104">本节介绍如何在<a class="reference internal" href="turtle.html#module-turtle" title="turtle: An educational framework for simple graphics applications"><code class="xref py py-mod docutils literal"><span class="pre">turtle</span></code></a>模块中的几个命令构建shell的简单示例。</span></p><p><span class="yiyi-st" id="yiyi-105">使用名为<code class="xref py py-meth docutils literal"><span class="pre">do_forward()</span></code>的方法将基本龟图命令(例如<a class="reference internal" href="turtle.html#turtle.forward" title="turtle.forward"><code class="xref py py-meth docutils literal"><span class="pre">forward()</span></code></a>添加到<a class="reference internal" href="#cmd.Cmd" title="cmd.Cmd"><code class="xref py py-class docutils literal"><span class="pre">Cmd</span></code></a>子类中)。</span><span class="yiyi-st" id="yiyi-106">参数被转换为一个数字并被分派到龟模块。</span><span class="yiyi-st" id="yiyi-107">docstring在shell提供的帮助实用程序中使用。</span></p><p><span class="yiyi-st" id="yiyi-108">该示例还包括使用<a class="reference internal" href="#cmd.Cmd.precmd" title="cmd.Cmd.precmd"><code class="xref py py-meth docutils literal"><span class="pre">precmd()</span></code></a>方法实现的基本记录和回放设施,该方法负责将输入转换为小写并将命令写入文件。</span><span class="yiyi-st" id="yiyi-109"><code class="xref py py-meth docutils literal"><span class="pre">do_playback()</span></code>方法读取文件,并将记录的命令添加到<code class="xref py py-attr docutils literal"><span class="pre">cmdqueue</span></code>以立即播放:</span></p><pre><code class="language-python"><span></span><span class="kn">import</span> <span class="nn">cmd</span><span class="o">,</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">turtle</span> <span class="k">import</span> <span class="o">*</span>
<span class="k">class</span> <span class="nc">TurtleShell</span><span class="p">(</span><span class="n">cmd</span><span class="o">.</span><span class="n">Cmd</span><span class="p">):</span>
<span class="n">intro</span> <span class="o">=</span> <span class="s1">'Welcome to the turtle shell. Type help or ? to list commands.</span><span class="se">\n</span><span class="s1">'</span>
<span class="n">prompt</span> <span class="o">=</span> <span class="s1">'(turtle) '</span>
<span class="n">file</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># ----- basic turtle commands -----</span>
<span class="k">def</span> <span class="nf">do_forward</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Move the turtle forward by the specified distance: FORWARD 10'</span>
<span class="n">forward</span><span class="p">(</span><span class="o">*</span><span class="n">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">do_right</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Turn turtle right by given number of degrees: RIGHT 20'</span>
<span class="n">right</span><span class="p">(</span><span class="o">*</span><span class="n">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">do_left</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Turn turtle left by given number of degrees: LEFT 90'</span>
<span class="n">left</span><span class="p">(</span><span class="o">*</span><span class="n">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">do_goto</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Move turtle to an absolute position with changing orientation. GOTO 100 200'</span>
<span class="n">goto</span><span class="p">(</span><span class="o">*</span><span class="n">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">do_home</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Return turtle to the home position: HOME'</span>
<span class="n">home</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">do_circle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Draw circle with given radius an options extent and steps: CIRCLE 50'</span>
<span class="n">circle</span><span class="p">(</span><span class="o">*</span><span class="n">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">do_position</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Print the current turle position: POSITION'</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Current position is </span><span class="si">%d</span><span class="s1"> </span><span class="si">%d</span><span class="se">\n</span><span class="s1">'</span> <span class="o">%</span> <span class="n">position</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">do_heading</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Print the current turle heading in degrees: HEADING'</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Current heading is </span><span class="si">%d</span><span class="se">\n</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">heading</span><span class="p">(),))</span>
<span class="k">def</span> <span class="nf">do_color</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Set the color: COLOR BLUE'</span>
<span class="n">color</span><span class="p">(</span><span class="n">arg</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">do_undo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Undo (repeatedly) the last turtle action(s): UNDO'</span>
<span class="k">def</span> <span class="nf">do_reset</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Clear the screen and return turtle to center: RESET'</span>
<span class="n">reset</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">do_bye</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Stop recording, close the turtle window, and exit: BYE'</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Thank you for using Turtle'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">bye</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="c1"># ----- record and playback -----</span>
<span class="k">def</span> <span class="nf">do_record</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Save future commands to filename: RECORD rose.cmd'</span>
<span class="bp">self</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_playback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="s1">'Playback commands from a file: PLAYBACK rose.cmd'</span>
<span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmdqueue</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">splitlines</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">precmd</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">file</span> <span class="ow">and</span> <span class="s1">'playback'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">line</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="p">)</span>
<span class="k">return</span> <span class="n">line</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">arg</span><span class="p">):</span>
<span class="s1">'Convert a series of zero or more numbers to an argument tuple'</span>
<span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">arg</span><span class="o">.</span><span class="n">split</span><span class="p">()))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">TurtleShell</span><span class="p">()</span><span class="o">.</span><span class="n">cmdloop</span><span class="p">()</span>
</code></pre><p><span class="yiyi-st" id="yiyi-110">下面是一个带有龟壳的示例会话,显示帮助功能,使用空行重复命令,以及简单的记录和回放设施:</span></p><div class="highlight-none"><div class="highlight"><pre><span></span>Welcome to the turtle shell. Type help or ? to list commands.
(turtle) ?
Documented commands (type help &lt;topic&gt;):
========================================
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
</pre></div></div></div></div></div>