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

行緩衝區

以下函式對行緩衝區進行操作

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

readline.write_history_file([filename])

將歷史記錄列表儲存到 readline 歷史記錄檔案,覆蓋任何現有檔案。 預設檔名為 ~/.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() 來截斷歷史檔案。負值表示歷史檔案大小不受限制。

歷史記錄列表

以下函式操作全域性歷史記錄列表

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 in 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 回撥的 startend 引數。在相同的輸入編輯場景中,這些值可能會因底層 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 模組的歷史記錄讀取和寫入功能,從使用者的 home 目錄自動載入和儲存名為 .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)