为什么 splitlines() 没有给出 Jupyter 中三点的预期结果?

tue*_*eda 16 python string jupyter-notebook

我相信下面的代码

s = '''
...
.o.
...
'''
print(s.splitlines())
Run Code Online (Sandbox Code Playgroud)

应该打印

['', '...', '.o.', '...']
Run Code Online (Sandbox Code Playgroud)

事实上,Python 正常执行时就是这种情况(在 Wandbox 上运行的示例在这里)。

但现实是无情的(一如既往);Google Colaboratory 打印没有“三点”的结果:

我还使用本地安装的 Jupyter(Python 3.7.13、Jupyter Notebook 6.4.12、IPython 7.34.0)尝试了相同的代码,它给出了与 Google Colaboratory 相同的结果。

有谁知道是什么原因导致三点删除?

Aso*_*cia 11

Google 协作将其解释...为提示的一部分。您可以将提示更改为其他字符串,结果将如您所愿

import sys
sys.ps2 = '<<<' # default value is ...

s = '''
...
.o.
...
'''
print(s.splitlines())
['', '...', '.o.', '...']
Run Code Online (Sandbox Code Playgroud)

编辑:正如 @user2357112 在评论和答案中指出的那样,更改提示不会影响这一点。在这里它似乎起作用了,因为在单元格的开头添加更多行会使 Ipython 解释器认为它们不再是提示的一部分。您可以将字符串更改为'\n...\n.o.\n...'作为解决方法。

  • 编辑“sys.ps2”实际上根本不会影响这一点。这似乎有帮助,但输出看起来正确的实际原因是您在笔记本单元格的顶部添加了更多行,这导致 IPython 不再认为“...”是提示。 (4认同)

use*_*ica 8

这是IPython 的一项功能。如果 IPython 认为您的输入看起来像是从另一个交互式会话复制粘贴的,它会在执行输入之前删除它认为是交互式提示的所有内容。

这应该可以轻松地从其他交互式 Python 会话复制和粘贴代码,而无需手动取消提示,但当您的实际代码看起来像是有交互式提示时,它会导致问题。


与其他答案所声称的相反,编辑sys.ps2根本不会影响这一点。提示正则表达式是硬编码的。对于当前的 IPython,您可以在 中查看逻辑IPython.core.inputtransformer2.PromptStripper,但 Google Colab 目前使用旧的 IPython 版本 5.5.0,您应该在其中查看IPython.core.inputtransformer.classic_prompt

@CoroutineInputTransformer.wrap
def classic_prompt():
    """Strip the >>>/... prompts of the Python interactive shell."""
    # FIXME: non-capturing version (?:...) usable?
    prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
    initial_re = re.compile(r'^>>>( |$)')
    # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
    turnoff_re = re.compile(r'^[%!]')
    return _strip_prompts(prompt_re, initial_re, turnoff_re)
Run Code Online (Sandbox Code Playgroud)

编辑sys.ps2看起来只是有帮助,因为_strip_prompts如果在前两行中没有找到任何提示,则停止寻找提示,而要编辑的额外代码sys.ps2意味着_strip_prompts在这些行中找不到任何提示。


不幸的是,如果你想禁用它,这将比编辑sys.ps2. 我认为没有方便的配置选项。我认为您必须检索输入清理转换器的列表并手动删除提示剥离器。在 Google Colab 当前使用的 IPython 版本上,如下所示:

physical_line_transforms = get_ipython().input_transformer_manager.physical_line_transforms
physical_line_transforms[:] = [transformer for transformer in physical_line_transforms
                               if transformer.coro.__name__ != '_strip_prompts']
Run Code Online (Sandbox Code Playgroud)

coro并且_strip_prompts是未记录的实现细节,但我认为没有更好的方法。

在更现代的 IPython 上,代码如下所示:

from IPython.core.inputtransformer2 import PromptStripper
cleanup_transformers = get_ipython().input_transformers_cleanup
cleanup_transformers[:] = [transformer for transformer in cleanup_transformers
                           if not isinstance(transformer, PromptStripper)]
Run Code Online (Sandbox Code Playgroud)

与其他代码片段不同,我认为这里的所有内容都是已记录的 IPython API 的一部分。


pau*_*her 7

我认为该行的开头表示交互模式...下的辅助提示(这是 Jupyter 和 Colaboratory 中的模式)。你不妨试试,它也是交互模式下的提示。>>>

我认为最好使用字符串'\n...\n.o.\n...'代替。