13. 交互式输入的编辑和历史记录

优质
小牛编辑
123浏览
2023-12-01

13. 交互式输入的编辑和历史记录

某些版本的 Python 解释器支持编辑当前的输入行和历史记录,类似于在 Korn shell 和 GNU Bash shell 中看到的功能。这是使用GNU Readline库实现的,它支持 Emacs 风格和 vi 风格的编辑。这个库有它自己的文档,在这里我不就重复了;然而,基本原理很容易解释。本章讲述的交互式编辑和历史记录功能在 Unix 版本和 Cygwin 版本中是可选的。

本章 是Mark Hammond的 PythonWin 包或者随 Python 一起发布的基于 TK 的 IDLE 环境的文档。基于 NT 系统的DOS和其它 DOS、Windows 系统上的命令行历史回溯是另一个话题。

13.1. 行编辑

如果支持,无论解释器打印主提示符还是从属提示符,输入行一直都可以编辑。可以使用传统的Emacs控制字符编辑当前行。其中最重要的是:C-A (Control-A)将光标移动到行首,C-E移到行尾,C-B将光标向左移动一个位置,C-F向右移动一个位置。退格键删除光标左侧的字符,C-D删除光标右侧的字符。C-k删掉一行中光标右侧的所有字符,C-y将最后一次删除的字符串粘贴到光标位置。C-下划线将撤消最近一次的更改;它可以重复执行并产生累积效果。

13.2. 历史记录

历史记录的工作方式如下。所有的非空输入行都保存在历史记录缓冲区中,当给出一个新的提示符时,你位于缓冲区最底部新的一行。C-P向上(往回)移动历史记录缓冲区中的一行,C-N向下移动一行。历史记录缓冲区中的任何一行都可以编辑;提示符的前面用一个星号标记修改的行。按Return键会将当前行传递给解释器。C-R开始逐渐向后搜索;C-S开始向前搜索。

13.3. 快捷键绑定

通过将命令放在一个名为~/.inputrc的初始化文件中,可以自定义快捷键和Readline 库的一些其他参数。快捷键绑定有如下方式

key-name: function-name

"string": function-name

也可以设置选项

set option-name value

例如:

# I prefer vi-style editing:
set editing-mode vi

# Edit using a single line:
set horizontal-scroll-mode On

# Rebind some keys:
Meta-h: backward-kill-word
"\C-u": universal-argument
"\C-x\C-r": re-read-init-file

注意 Python 中Tab键默认绑定的是插入一个制表符而不是 Readline 的默认文件名补全功能。如果你坚持这样做,你可以放置一行

Tab: complete

在你的~/.inputrc中。(当然,如果你习惯使用Tab作为缩进,这会使得输入续行的缩进很困难。)

可以选择变量和模块名自动补全功能。若要在解释器的交互模式中启用这个功能,添加以下内容到你的启动文件:[1]

import rlcompleter, readline
readline.parse_and_bind('tab: complete')

这将Tab键绑定到补全功能,所以按Tab键两次将会给出补全的建议;它会查找 Python 语句名称、当前的局部变量以及有效的模块名。例如点分表达式string.a,它会先解析最后一个点'.'之前的表达式,然后根据结果对象给出建议补全的内容。注意如果表达式得到的对象带有getattr()方法,这可能会执行应用程序定义的代码。

更有用的启动文件可能看起来像下面这个示例。注意下面的示例删除了它创建的名称,一旦这些名称不再需要;这是因为启动文件与交互式命令在相同的命名空间中执行,删除这些名称可以避免在交互式环境中产生副作用。你可能发现保留一些导入的模块有时也会很方便,例如os,因为在大多数与解释器的交互中都需要它。

# Add auto-completion and a stored history file of commands to your Python
# interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
# bound to the Esc key by default (you can change it - see readline docs).
#
# Store the file in ~/.pystartup, and set an environment variable to point
# to it:  "export PYTHONSTARTUP=~/.pystartup" in bash.

import atexit
import os
import readline
import rlcompleter

historyPath = os.path.expanduser("~/.pyhistory")

def save_history(historyPath=historyPath):
    import readline
    readline.write_history_file(historyPath)

if os.path.exists(historyPath):
    readline.read_history_file(historyPath)

atexit.register(save_history)
del os, atexit, readline, rlcompleter, save_history, historyPath

13.4. 其它交互式解释器

与早期版本的解释器相比,现在是向前巨大的进步;然而,有些愿望还是没有实现:如果能对连续的行给出正确的建议就更好了(解析器知道下一行是否需要缩进)。补全机制可以使用解释器的符号表。检查(或者只是建议)匹配的括号、 引号的命令等也会非常有用。

一个增强的交互式解释器是IPython,它已经存在相当一段时间,具有tab补全、 对象exploration 和高级的历史记录功能。它也可以彻底定制并嵌入到其他应用程序中。另一个类似的增强的交互式环境是bpython

脚注

| [1] | 当你启动一个交互式解释器时,Python将执行环境变量PYTHONSTARTUP指定的文件中的内容。若还要定制化非交互式的Python,请参阅定制化模块。 | |-----|-----|