Skip to main content

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。

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

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)

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

6.7.4. 历史列表

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

readline.clear_history()

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

readline.get_current_history_length()

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

readline.get_history_item(index)

返回 index 历史记录项目的当前内容。项目索引是基于1的。这会在底层库中调用 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 implementation detail: Auto history is enabled by default, and changes to this do not persist across multiple sessions.

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])

设置或删除完成器函数。如果指定了 function,它将用作新的完成函数;如果省略或 None,则已经安装的任何完成器功能已删除。完成器函数被称为 function(text, state),用于 012,...中的 state,直到它返回非字符串值。它应该返回从 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 回调的 startend 参数。

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),每次需要显示匹配时。

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在 交互模式 中运行时,此代码实际上自动运行(参见 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_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)