MacOS上Python REPL的Tab补全

53 投票
2 回答
15520 浏览
提问于 2025-04-16 23:55

在升级到Lion之前,我在终端的Python环境中可以使用Tab键自动补全。按照这些步骤,我成功地让Tab键补全功能正常工作。

但是自从升级到Lion后,我在Python的终端会话中就无法使用Tab键补全了。我完全按照之前的步骤操作,但还是不行。

我在想,Lion中的readline模块是不是有什么不同?现在连接到'tab:complete'选项似乎不再有效。我在想,是终端忽略了readline,还是Python本身的问题。

Python版本:2.7.1

编辑:

这里说的Tab键补全,意思是我可以像下面这样操作:

# django
import MyModel
MyModel.objects.a[TAB] # will complete to all()

2 个回答

16

由于它使用了libedit/editline,所以启用自动补全的语法有点不同。

你可以先通过输入以下命令来强制使用emacs的按键绑定(如果我没记错的话,这和readline是一样的):

readline.parse_and_bind("bind -e")

接着,你可以把TAB键设置为自动补全的功能(可以查看editrc的手册):

readline.parse_and_bind("bind '\t' rl_complete")

如果你想支持缩进并且有历史记录(这个可以在网上找到),它应该看起来像这样(除非我搞错了):

import readline,rlcompleter

### Indenting
class TabCompleter(rlcompleter.Completer):
    """Completer that supports indenting"""
    def complete(self, text, state):
        if not text:
            return ('    ', None)[state]
        else:
            return rlcompleter.Completer.complete(self, text, state)

readline.set_completer(TabCompleter().complete)

### Add autocompletion
if 'libedit' in readline.__doc__:
    readline.parse_and_bind("bind -e")
    readline.parse_and_bind("bind '\t' rl_complete")
else:
    readline.parse_and_bind("tab: complete")

### Add history
import os
histfile = os.path.join(os.environ["HOME"], ".pyhist")
try:
    readline.read_history_file(histfile)
except IOError:
    pass
import atexit
atexit.register(readline.write_history_file, histfile)
del histfile
117

苹果的操作系统 OS X 并没有自带 GNU 的 readline。不过,它提供了一个叫做 BSD libedit 的工具,这个工具有一个和 readline 兼容的接口。苹果自带的 Python 版本,以及从 python.org 下载的 64 位和 32 位 Python,都是用 libedit 构建的。问题在于,libedit 支持的命令和 readline 的命令完全不一样(你可以在这里查看相关讨论 这里)。传统的 32 位 python.org 安装包使用的是 GNU readline,还有一些其他的第三方 Python 版本,比如 MacPorts,也使用这个工具。你可能之前用的就是这样的 Python,而不是最近的苹果版本。除了修改 Django,你还有几个选择:可以安装一个第三方的替代模块 readline;或者使用一个自带 GNU readline 的 Python。不过,建议你不要在 10.7 上使用 python.org 的 32 位版本,因为不幸的是,10.7 上的 Xcode 4 不再包含 gcc-4.0 和这些 Python 需要的 OS X 10.4u SDK,这些都是用来构建和安装带有 C 扩展模块的包的。

在 Python 启动文件中加入以下内容,可以为 libedit 接口和常规的 readline 模块启用 Tab 补全功能。关于 Python 启动文件的更多信息,请查看这里

import readline
import rlcompleter
if 'libedit' in readline.__doc__:
    readline.parse_and_bind("bind ^I rl_complete")
else:
    readline.parse_and_bind("tab: complete")

撰写回答