重要

本文档涵盖 IPython 6.0 及更高版本。从 6.0 版本开始,IPython 不再支持与低于 3.3 的 Python 版本(包括所有版本的 Python 2.7)兼容。

如果您正在寻找与 Python 2.7 兼容的 IPython 版本,请使用 IPython 5.x LTS 版本并参阅其文档(LTS 是长期支持版本)。

特定配置详细信息

自定义提示符

在版本 5.0 中更改。

从 IPython 5 开始,提示符作为 Pygments 令牌列表生成,这些令牌是 (token_type, text) 的元组。您可以通过编写生成令牌列表的方法来自定义提示符。

有四种提示符

  • in 提示符显示在输入的第一行之前(默认类似于 In [1]:)。

  • continuation 提示符显示在输入的后续行之前(默认类似于 ...:)。

  • rewrite 提示符显示为突出显示特殊语法是如何解释的(默认类似于 ----->)。

  • out 提示符显示在评估输入的结果之前(默认类似于 Out[1]:)。

自定义提示符一起作为类提供。如果您只想自定义其中一些提示符,请从 IPython.terminal.prompts.Prompts 继承,它定义了默认值。必需的界面如下所示

class MyPrompts(shell)

提示符样式定义。shell 是对 TerminalInteractiveShell 实例的引用。

in_prompt_tokens()
continuation_prompt_tokens(self, width=None)
rewrite_prompt_tokens()
out_prompt_tokens()

将各个提示符作为 (token_type, text) 元组列表返回。

对于延续提示,宽度是一个整数,表示终端列中提示区域的宽度。

这是一个示例提示类,它将在输入提示中显示当前的工作目录

from IPython.terminal.prompts import Prompts, Token
import os

class MyPrompt(Prompts):
     def in_prompt_tokens(self):
         return [(Token, os.getcwd()),
                 (Token.Prompt, ' >>>')]

要设置新提示,将其分配给 IPython shell 的 prompts 属性

In [2]: ip = get_ipython()
   ...: ip.prompts = MyPrompt(ip)

/home/bob >>> # it works

请参阅 IPython/example/utils/cwd_prompt.py,了解如何编写扩展以自定义提示的示例。

在 IPython 中或在启动脚本中,你可以通过将 get_ipython().prompts 设置为类的实例来使用自定义提示类。在配置中,TerminalInteractiveShell.prompts_class 可以设置为类对象或其完整可导入名称的字符串。

要在提示中包含不可见的终端控制序列,请使用 Token.ZeroWidthEscape 作为令牌类型。计算宽度时会忽略此类型的令牌。

提示中的颜色由令牌类型和突出显示样式决定;有关更多详细信息,请参阅下文。默认提示中使用的令牌是 PromptPromptNumOutPromptOutPromptNum

终端颜色

在版本 5.0 中更改。

有两个主要配置选项控制颜色。

InteractiveShell.colors 设置回溯和对象信息(例如 zip? 的输出)的颜色。如果下面的选项设置为 'legacy',它也可能会影响其他内容。它有四个不区分大小写的值:'nocolor', 'neutral', 'linux', 'lightbg'。默认值为neutral,它应该可以在深色或浅色终端背景上辨认。linux 针对深色背景进行了优化,而 lightbg 针对浅色背景进行了优化。

TerminalInteractiveShell.highlighting_style 确定提示颜色和语法突出显示。它采用 Pygments 样式的名称(作为字符串)或类(作为 pygments.style.Style 的子类),或特殊值 'legacy' 来根据 InteractiveShell.colors 选择样式。

你可以通过运行以下命令查看系统上可用的 Pygments 样式

from pygments.styles import get_all_styles
list(get_all_styles())

此外,TerminalInteractiveShell.highlighting_style_overrides 可以覆盖突出显示中的特定样式。它应该是一个字典,将 Pygments 令牌类型映射到定义样式的字符串。请参阅 Pygments 文档,了解用于定义样式的语言。

分页器中的颜色

在某些系统上,默认分页器在 ANSI 颜色代码方面存在问题。要配置默认分页器以允许这些

  1. 将环境 PAGER 变量设置为 less

  2. 将环境 LESS 变量设置为 -r(以及你始终希望默认传递给 less 的任何其他选项)。这会指示 less 正确解释控制序列,这是将颜色信息提供给终端的方式。

编辑器配置

IPython 可以通过多种不同方式与文本编辑器集成

  • 编辑器(例如 (X)EmacsvimTextMate)可以将代码发送到 IPython 中执行。

  • IPython 的 %edit 魔术命令可以打开一个编辑器来编辑代码块。

%edit 命令(及其别名 %ed)将调用环境中设置的编辑器作为 EDITOR。如果未设置此变量,则在 Linux/Unix 下默认为 vi,在 Windows 下默认为记事本。您可能希望正确设置此变量并将其设置为一个启动时间不长的轻量级编辑器(即,不是 Emacs 的新实例)。这样,您就可以快速使用真正的编辑器的强大功能在 IPython 中编辑多行代码。

您还可以通过在 ipython_config.py 中设置 TerminalInteractiveShell.editor 来控制编辑器。

Vim

Paul Ivanov 的 vim-ipython 为 vim 提供了强大的 IPython 集成。

(X)Emacs

如果您是专门的 Emacs 用户,并且希望在调用 IPython 的 %edit 魔术命令时使用 Emacs,则应设置 Emacs 服务器,以便由原始进程处理新请求。这意味着几乎不需要花费时间来处理请求(假设 Emacs 进程已经在运行)。为此,您需要将 EDITOR 环境变量设置为“emacsclient”。然后,可以使用 Francois Pinard 提供的以下代码在 .emacs 文件中启用服务器

(defvar server-buffer-clients)
(when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm))
  (server-start)
  (defun fp-kill-server-with-buffer-routine ()
    (and server-buffer-clients (server-done)))
  (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine))

感谢 Alexander Schmolck 和 Prabhu Ramachandran 的工作,目前 (X)Emacs 和 IPython 在其他方面相处得非常好。

对于 (X)EMacs >= 24,您可以在 python 模式下使用以下命令启用 IPython

(require 'python)
(setq python-shell-interpreter "ipython")

键盘快捷键

在 8.11 版本中添加。

您可以使用 TerminalInteractiveShell.shortcuts 特性修改、禁用或修改 IPython 终端的键盘快捷键。

快捷键列表可在配置 IPython IPython 快捷键 部分中找到。

高级配置

在版本 5.0 中更改。

创建自定义命令需要将自定义代码添加到 启动文件

from IPython import get_ipython
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.keys import Keys
from prompt_toolkit.filters import HasFocus, HasSelection, ViInsertMode, EmacsInsertMode

ip = get_ipython()
insert_mode = ViInsertMode() | EmacsInsertMode()

def insert_unexpected(event):
    buf = event.current_buffer
    buf.insert_text('The Spanish Inquisition')
# Register the shortcut if IPython is using prompt_toolkit
if getattr(ip, 'pt_app', None):
    registry = ip.pt_app.key_bindings
    registry.add_binding(Keys.ControlN,
                     filter=(HasFocus(DEFAULT_BUFFER)
                             & ~HasSelection()
                             & insert_mode))(insert_unexpected)

这里有一个第二个示例,它将键序列 jk 绑定到在插入模式下切换到 VI 输入模式 Normal

from IPython import get_ipython
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.filters import HasFocus, ViInsertMode
from prompt_toolkit.key_binding.vi_state import InputMode

ip = get_ipython()

def switch_to_navigation_mode(event):
   vi_state = event.cli.vi_state
   vi_state.input_mode = InputMode.NAVIGATION

if getattr(ip, 'pt_app', None):
   registry = ip.pt_app.key_bindings
   registry.add_binding(u'j',u'k',
                        filter=(HasFocus(DEFAULT_BUFFER)
                                 & ViInsertMode()))(switch_to_navigation_mode)

有关过滤器以及您可以使用 event 对象执行的操作的更多信息,请参阅 prompt_toolkit 文档

按 Enter 执行

在终端 IPython shell 中,它默认使用 prompt_toolkit 接口,按下 Enter 键的语义含义可能不明确。在某些情况下,Enter 应执行代码,而在其他情况下,它应添加新行。IPython 使用启发式方法来决定在光标位置执行还是插入新行。例如,如果我们检测到当前代码不是有效的 Python,则用户很可能正在编辑代码,正确的行为可能是插入新行。如果当前代码是一个简单的语句,如 ord('*'),则正确的行为可能是执行。虽然确切的期望语义通常因用户而异。

由于 Enter 的确切行为不明确,因此它被特别设计为允许用户完全配置他们喜欢的行为。因此,你可以让 enter 始终执行代码。如果你喜欢更花哨的行为,你需要动手实践,阅读 prompt_toolkit 和 IPython 文档。请参阅 PR #10500,设置 c.TerminalInteractiveShell.handle_return 选项,并从以下示例中获得灵感,该示例仅在输入以感叹号或模数字符 (!%) 开头时自动执行输入。要使用以下代码,请将其添加到你的 IPython 配置中

def custom_return(shell):

    """This function is required by the API. It takes a reference to
    the shell, which is the same thing `get_ipython()` evaluates to.
    This function must return a function that handles each keypress
    event. That function, named `handle` here, references `shell`
    by closure."""

    def handle(event):

        """This function is called each time `Enter` is pressed,
        and takes a reference to a Prompt Toolkit event object.
        If the current input starts with a bang or modulo, then
        the input is executed, otherwise a newline is entered,
        followed by any spaces needed to auto-indent."""

        # set up a few handy references to nested items...

        buffer = event.current_buffer
        document = buffer.document
        text = document.text

        if text.startswith('!') or text.startswith('%'): # execute the input...

            buffer.accept_action.validate_and_handle(event.cli, buffer)

        else: # insert a newline with auto-indentation...

            if document.line_count > 1: text = text[:document.cursor_position]
            indent = shell.check_complete(text)[1]
            buffer.insert_text('\n' + indent)

            # if you just wanted a plain newline without any indentation, you
            # could use `buffer.insert_text('\n')` instead of the lines above

    return handle

c.TerminalInteractiveShell.handle_return = custom_return