# 6.7. `readline` —— GNU readline接口

`readline`模块定义了许多函数，以便于从Python解释器完成和读取/写入历史文件。此模块可以直接使用，也可以通过`rlcompleter`模块使用，该模块支持在交互式提示符处完成Python标识符。使用此模块进行的设置会影响解释器的交互式提示和由内置`input()`函数提供的提示的行为。

注意

底层的Readline库API可以通过`libedit`库而不是GNU readline来实现。在MacOS X上，`readline`模块检测在运行时使用哪个库。

`libedit`的配置文件与GNU readline的配置文件不同。如果以编程方式加载配置字符串，您可以检查`readline.__doc__`中的文本“libedit”，以区分GNU readline和libedit。

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

## 6.7.1.Init文件

以下函数与init文件和用户配置相关：

`readline.``parse_and_bind`(string)

  执行string参数中提供的init行。这会调用底层库中的`rl_parse_and_bind()`。

`readline.``read_init_file`([filename])

  执行readline初始化文件。默认文件名是所使用的最后一个文件名。这会调用底层库中的`rl_read_init_file()`。

## 6.7.2.行缓冲

以下功能对行缓冲区进行操作：

`readline.``get_line_buffer`()

  返回行缓冲区的当前内容（`rl_line_buffer`在底层库中）。

`readline.``insert_text`(string)

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

`readline.``redisplay`()

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

## 6.7.3.历史记录文件

以下功能操作历史文件：

`readline.``read_history_file`([filename])

  加载阅读历史记录文件，并将其附加到历史记录列表。默认文件名为`~/.history`。这会调用底层库中的`read_history()`。

`readline.``write_history_file`([filename])

  将历史记录列表保存到阅读历史记录文件，覆盖任何现有文件。默认文件名为`~/.history`。这会调用底层库中的`write_history()`。

`readline.``append_history_file`(nelements[, filename])

  将最后的nelements项目追加到文件中。默认文件名为`~/.history`。文件必须已存在。这会在底层库中调用`append_history()`。此函数仅在Python是为支持它的库的版本编译时才存在。

  版本3.5中的新功能。

`readline.``get_history_length`()
`readline.``set_history_length`(length)

  设置或返回要保存在历史记录文件中的所需行数。通过调用底层库中的`history_truncate_file()`，`write_history_file()`函数使用此值截断历史记录文件。负值意味着无限的历史文件大小。

## 6.7.4.历史列表

以下功能对全局历史列表进行操作：

`readline.``clear_history`()

  清除当前历史记录。这在底层库中调用`clear_history()`。如果Python是为支持它的库的版本编译的，Python函数才存在。

`readline.``get_current_history_length`()

  返回当前在历史记录中的项目数。（这不同于`get_history_length()`，它返回将写入历史文件的最大行数。）

`readline.``get_history_item`(index)

  返回索引的历史记录项目的当前内容。项目索引是从1开始的。这会调用底层库中的`history_get()`。

`readline.``remove_history_item`(pos)

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

`readline.``replace_history_item`(pos, line)

  用行替换其位置指定的历史记录项。位置是零为基础。这会调用底层库中的`replace_history_entry()`。

`readline.``add_history`(line)

  将行附加到历史记录缓冲区，就好像它是最后一行键入的。这会调用底层库中的`add_history()`。

## 6.7.5.启动挂接

`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是为支持它的库的版本编译时才存在。

## 6.7.6.完成

以下功能涉及实现自定义词语完成功能。这通常由Tab键操作，并且可以建议并自动完成键入的单词。默认情况下，Readline设置为由`rlcompleter`使用以完成交互式解释器的Python标识符。如果`readline`模块要与自定义完成程序一起使用，则应设置一组不同的字分隔符。

`readline.``set_completer`([function])

  设置或删除完成器功能。如果指定函数，它将用作新的完成函数；如果省略或`None`，则已删除已安装的任何完成器函数。The completer function is called as `function(text, state)`, for state in `0`, `1`, `2`, ..., until it returns a non-string value. 它应该返回从文本开始的下一个可能的完成。

  安装的completionter函数由传递给底层库中的`rl_completion_matches()`的entry_func回调调用。文本字符串来自基础库的`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参数。

`readline.``set_completer_delims`(string)
`readline.``get_completer_delims`()

  设置或获取完成的单词分隔符。这些决定了要考虑完成的字的开始（完成范围）。这些函数访问底层库中的`rl_completer_word_break_characters`变量​​。

`readline.``set_completion_display_matches_hook`([function])

  设置或删除完成显示功能。如果指定函数，它将用作新的完成显示函数；如果省略或`None`，已安装的任何完成显示功能已删除。这会设置或清除底层库中的`rl_completion_display_matches_hook`回调。每次匹配需要时，完成显示功能称为`功能（替换， [matches]， longest_match_length）显示。`

## 6.7.7.示例

以下示例演示如何使用`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在interactive mode中运行时，该代码实际上自动运行（参见Readline configuration）。

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

    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_history_length()
    except FileNotFoundError:
        open(histfile, 'wb').close()
        h_len = 0

    def save(prev_h_len, histfile):
        new_h_len = readline.get_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)