readline — GNU readline 接口


readline 模块定义了许多函数,以便于从 Python 解释器中进行补全和历史文件的读写。这个模块可以直接使用,也可以通过 rlcompleter 模块使用,后者支持交互式提示符下的 Python 标识符补全。使用此模块进行的设置会影响解释器的交互式提示符和内置 input() 函数提供的提示符的行为。

Readline 键绑定可以通过初始化文件配置,通常是您的主目录中的 .inputrc。有关该文件格式和允许的结构以及 Readline 库功能的常规信息,请参阅 GNU Readline 手册中的 Readline 初始化文件

可用性: 非 Android、非 iOS、非 WASI。

该模块在移动平台WebAssembly 平台上不受支持。

备注

底层 Readline 库 API 可以由 editline (libedit) 库而非 GNU readline 实现。在 macOS 上,readline 模块会在运行时检测正在使用的库。

editline 的配置文件与 GNU readline 不同。如果您以编程方式加载配置字符串,可以使用 backend 来确定正在使用哪个库。

如果您在 macOS 上使用 editline/libedit readline 仿真,则位于您的主目录中的初始化文件名为 .editrc。例如,~/.editrc 中的以下内容将开启 *vi* 键绑定和 TAB 补全

python:bind -v
python:bind ^I rl_complete

另请注意,不同的库可能使用不同的历史文件格式。切换底层库时,现有历史文件可能会变得不可用。

readline.backend

正在使用的底层 Readline 库的名称,可以是 "readline""editline"

在 3.13 版本加入。

初始化文件

以下函数与初始化文件和用户配置相关

readline.parse_and_bind(string)

执行在 *string* 参数中提供的初始化行。这会调用底层库中的 rl_parse_and_bind()

readline.read_init_file([filename])

执行 readline 初始化文件。默认文件名为上次使用的文件名。这会调用底层库中的 rl_read_init_file()。如果给定文件名,则会引发一个 审计事件 open,文件名为该文件名;否则,文件名为 "<readline_init_file>",无论库解析到哪个文件。

3.14 版本新增: 增加了审计事件。

行缓冲区

以下函数对行缓冲区进行操作

readline.get_line_buffer()

返回行缓冲区的当前内容(底层库中的 rl_line_buffer)。

readline.insert_text(string)

在光标位置插入文本到行缓冲区中。这会调用底层库中的 rl_insert_text(),但忽略返回值。

readline.redisplay()

更改屏幕显示以反映行缓冲区的当前内容。这会调用底层库中的 rl_redisplay()

历史文件

以下函数对历史文件进行操作

readline.read_history_file([filename])

加载 readline 历史文件,并将其附加到历史列表中。默认文件名为 ~/.history。这会调用底层库中的 read_history(),如果给定文件名,则会引发一个 审计事件 open,文件名为该文件名;否则,文件名为 "~/.history"

3.14 版本新增: 增加了审计事件。

readline.write_history_file([filename])

将历史列表保存到 readline 历史文件,覆盖任何现有文件。默认文件名为 ~/.history。这会调用底层库中的 write_history(),如果给定文件名,则会引发一个 审计事件 open,文件名为该文件名;否则,文件名为 "~/.history"

3.14 版本新增: 增加了审计事件。

readline.append_history_file(nelements[, filename])

将历史记录中的最后 *nelements* 项附加到文件中。默认文件名为 ~/.history。文件必须已经存在。这会调用底层库中的 append_history()。此函数仅在 Python 编译的库版本支持它时才存在。如果给定文件名,则会引发一个 审计事件 open,文件名为该文件名;否则,文件名为 "~/.history"

在 3.5 版本加入。

3.14 版本新增: 增加了审计事件。

readline.get_history_length()
readline.set_history_length(length)

设置或返回要保存在历史文件中的所需行数。write_history_file() 函数使用此值通过调用底层库中的 history_truncate_file() 来截断历史文件。负值表示历史文件大小无限制。

历史列表

以下函数对全局历史列表进行操作

readline.clear_history()

清除当前历史记录。这会调用底层库中的 clear_history()。此 Python 函数仅在 Python 编译的库版本支持它时才存在。

readline.get_current_history_length()

返回历史记录中当前项目的数量。(这与 get_history_length() 不同,后者返回将写入历史文件的最大行数。)

readline.get_history_item(index)

返回 *index* 处历史项目的当前内容。项目索引是基于一的。这会调用底层库中的 history_get()

readline.remove_history_item(pos)

从历史记录中删除由其位置指定的历史项目。位置是基于零的。这会调用底层库中的 remove_history()

readline.replace_history_item(pos, line)

用 *line* 替换由其位置指定的历史项目。位置是基于零的。这会调用底层库中的 replace_history_entry()

readline.add_history(line)

将 *line* 附加到历史缓冲区,就像它是最后输入的行一样。这会调用底层库中的 add_history()

readline.set_auto_history(enabled)

启用或禁用通过 readline 读取输入时自动调用 add_history()。*enabled* 参数应该是一个布尔值,当为 true 时启用自动历史记录,当为 false 时禁用自动历史记录。

在 3.6 版本加入。

CPython 实现细节: 自动历史记录默认启用,并且对此的更改不会在多次会话之间持续存在。

启动钩子

readline.set_startup_hook([function])

设置或移除由底层库的 rl_startup_hook 回调调用的函数。如果指定了 *function*,它将用作新的钩子函数;如果省略或为 None,则移除任何已安装的函数。钩子在 readline 打印第一个提示符之前不带参数地调用。

readline.set_pre_input_hook([function])

设置或移除由底层库的 rl_pre_input_hook 回调调用的函数。如果指定了 *function*,它将用作新的钩子函数;如果省略或为 None,则移除任何已安装的函数。钩子在打印第一个提示符之后且在 readline 开始读取输入字符之前不带参数地调用。此函数仅在 Python 编译的库版本支持它时才存在。

补全

以下函数与实现自定义单词补全函数有关。这通常通过 Tab 键操作,可以建议并自动补全正在输入的单词。默认情况下,Readline 设置为由 rlcompleter 用于为交互式解释器补全 Python 标识符。如果 readline 模块要与自定义补全器一起使用,则应设置不同的单词分隔符。

readline.set_completer([function])

设置或移除补全函数。如果指定了 *function*,它将用作新的补全函数;如果省略或为 None,则移除任何已安装的补全函数。补全函数以 function(text, state) 的形式调用,其中 *state* 为 0, 1, 2, …,直到它返回一个非字符串值。它应该返回以 *text* 开头的下一个可能的补全。

已安装的补全函数由传递给底层库中的 rl_completion_matches() 的 *entry_func* 回调调用。*text* 字符串来自底层库的 rl_attempted_completion_function 回调的第一个参数。

readline.get_completer()

获取补全函数,如果没有设置补全函数则返回 None

readline.get_completion_type()

获取正在尝试的补全类型。这会将底层库中的 rl_completion_type 变量作为整数返回。

readline.get_begidx()
readline.get_endidx()

获取补全范围的起始或结束索引。这些索引是传递给底层库的 rl_attempted_completion_function 回调的 *start* 和 *end* 参数。在相同的输入编辑场景中,这些值可能因底层 C readline 实现而异。例如:libedit 已知与 libreadline 的行为不同。

readline.set_completer_delims(string)
readline.get_completer_delims()

设置或获取补全的单词分隔符。这些确定了要考虑补全的单词的开头(补全范围)。这些函数访问底层库中的 rl_completer_word_break_characters 变量。

readline.set_completion_display_matches_hook([function])

设置或移除补全显示函数。如果指定了 *function*,它将用作新的补全显示函数;如果省略或为 None,则移除任何已安装的补全显示函数。这会设置或清除底层库中的 rl_completion_display_matches_hook 回调。补全显示函数以 function(substitution, [matches], longest_match_length) 的形式调用,每次需要显示匹配项时调用一次。

示例

以下示例演示了如何使用 readline 模块的历史读取和写入函数来自动加载和保存用户主目录中名为 .python_history 的历史文件。以下代码通常会在用户 PYTHONSTARTUP 文件中的交互式会话期间自动执行。

import atexit
import os
import readline

histfile = os.path.join(os.path.expanduser("~"), ".python_history")
try:
    readline.read_history_file(histfile)
    # default history len is -1 (infinite), which may grow unruly
    readline.set_history_length(1000)
except FileNotFoundError:
    pass

atexit.register(readline.write_history_file, histfile)

此代码实际上在 Python 以 交互模式 运行时自动运行(参见 Readline 配置)。

以下示例实现了相同的目标,但通过仅附加新历史记录来支持并发交互式会话。

import atexit
import os
import readline
histfile = os.path.join(os.path.expanduser("~"), ".python_history")

try:
    readline.read_history_file(histfile)
    h_len = readline.get_current_history_length()
except FileNotFoundError:
    open(histfile, 'wb').close()
    h_len = 0

def save(prev_h_len, histfile):
    new_h_len = readline.get_current_history_length()
    readline.set_history_length(1000)
    readline.append_history_file(new_h_len - prev_h_len, histfile)
atexit.register(save, h_len, histfile)

以下示例扩展了 code.InteractiveConsole 类以支持历史记录保存/恢复。

import atexit
import code
import os
import readline

class HistoryConsole(code.InteractiveConsole):
    def __init__(self, locals=None, filename="<console>",
                 histfile=os.path.expanduser("~/.console-history")):
        code.InteractiveConsole.__init__(self, locals, filename)
        self.init_history(histfile)

    def init_history(self, histfile):
        readline.parse_and_bind("tab: complete")
        if hasattr(readline, "read_history_file"):
            try:
                readline.read_history_file(histfile)
            except FileNotFoundError:
                pass
            atexit.register(self.save_history, histfile)

    def save_history(self, histfile):
        readline.set_history_length(1000)
        readline.write_history_file(histfile)