如何启用Python REPL的自动补全并允许换行制表符

16 投票
1 回答
15170 浏览
提问于 2025-04-18 18:07

我现在在 ~/.pythonrc 文件里设置了一些内容,以便在 Python 的交互式环境中启用自动补全功能:

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

但是,当我在新的一行开始时按 tab(比如在一个 for 循环内部),我得到的是一堆建议,而不是一个 tab

理想情况下,我希望只有在输入了非空白字符后,才会出现建议。

~/.pythonrc 中实现这个功能简单吗?

1 个回答

34

你可以直接使用IPython。它有自动补全和自动缩进的功能,特别适合处理循环或函数定义。比如说:

# Ipython prompt
In [1]: def stuff(x):
   ...:     |
#           ^ cursor automatically moves to this position

要安装它,你可以使用pip

pip install ipython

如果你还没有安装pip,可以按照这个页面上的说明来安装。在python 3.4及以上版本中,pip是默认安装的。

如果你是在Windows系统上,可以去这个页面下载IPython的安装包(还有很多其他可能难以安装的Python库)。


不过,如果因为某种原因你无法安装IPython,Brandon Invergo创建了一个Python启动脚本,这个脚本为Python解释器添加了几个功能,其中就包括自动缩进。他将这个脚本以GPL v3的协议发布,并在这里提供了源代码。

我把处理自动缩进的代码复制在下面。为了让它在我的Python 3.4解释器上正常工作,我在第11行添加了indent = ''

import readline

def rl_autoindent():
    """Auto-indent upon typing a new line according to the contents of the
    previous line.  This function will be used as Readline's
    pre-input-hook.

    """
    hist_len = readline.get_current_history_length()
    last_input = readline.get_history_item(hist_len)
    indent = ''
    try:
        last_indent_index = last_input.rindex("    ")
    except:
        last_indent = 0
    else:
        last_indent = int(last_indent_index / 4) + 1
    if len(last_input.strip()) > 1:
        if last_input.count("(") > last_input.count(")"):
            indent = ''.join(["    " for n in range(last_indent + 2)])
        elif last_input.count(")") > last_input.count("("):
            indent = ''.join(["    " for n in range(last_indent - 1)])
        elif last_input.count("[") > last_input.count("]"):
            indent = ''.join(["    " for n in range(last_indent + 2)])
        elif last_input.count("]") > last_input.count("["):
            indent = ''.join(["    " for n in range(last_indent - 1)])
        elif last_input.count("{") > last_input.count("}"):
            indent = ''.join(["    " for n in range(last_indent + 2)])
        elif last_input.count("}") > last_input.count("{"):
            indent = ''.join(["    " for n in range(last_indent - 1)])
        elif last_input[-1] == ":":
            indent = ''.join(["    " for n in range(last_indent + 1)])
        else:
            indent = ''.join(["    " for n in range(last_indent)])
    readline.insert_text(indent)

readline.set_pre_input_hook(rl_autoindent)

撰写回答