更改Python交互式提示符“>>>”

29

我记得在Python 3.5文档中阅读到了如何更改Python交互式提示符上的>>>,例如调用help()会将其更改为help>

但出于某种原因,当我回去尝试回忆时,我就是找不到它的说明。有人知道是否可能吗?

3个回答

31

你记得的没错。

这在 sys 模块中定义了两个字符串变量 (sys.ps1 和 sys.ps2):

指定解释器主提示符和辅助提示符的字符串。这些变量仅在交互模式下定义。在此情况下,它们的初始值分别为'>>> '和'... '。如果将非字符串对象分配给任一变量,则每次解释器准备读取新的交互式命令时都会重新计算其str();这可用于实现动态提示符。

例如:

   >>> import sys
   >>> sys.ps1 = "3.5>>> "
   3.5>>> sys.ps2 = "3.5... "
   3.5>>>

太好了!谢谢。我不记得在哪里读到过,但我很高兴自己没有疯掉。 - MutantOctopus
也适用于Python 2.7.12版本。 - Bob Stein
无论是在Idle中的3.5.0还是2.7.10版本,它对我都不起作用。但是在Windows控制台中它确实可以工作。 - Mark Ransom
@MarkRansom:我从未考虑过Idle。不过它确实可以在Linux和Windows控制台上工作。 - Gerrat
2
一个很酷的点子:定义sys.ps1 = ""和sys.ps2 = "",这样就可以轻松地将终端输出从>>>和...复制粘贴到编辑器中。 - jasonleonhard

11

将其设置为以下任一选项都很好:

  1. 一个颜色以获得更好的视觉效果
  2. 一个空白空格以便于复制/粘贴操作

将此内容粘贴到你的Bash shell中:

tee ~/.pyrc <<EOF
#!/usr/bin/env python3
import sys

# You also need \x01 and \x02 to separate escape sequence, due to:
# https://dev59.com/IGox5IYBdhLWcg3wDgIz#9468954
sys.ps1='\x01\x1b[1;49;33m\x02>>>\x01\x1b[0m\x02 '  # bright yellow
sys.ps2='\x01\x1b[1;49;31m\x02...\x01\x1b[0m\x02 '  # bright red
EOF

最后在你的~/.bash_profile文件中添加以下一行:

export PYTHONSTARTUP=~/.pyrc


如果你使用的是Windows系统,请使用以下其中之一:

# Set it Temperarily (for this session)
$env:PYTHONSTARTUP="C:\Users\<USERNAME>\.pyrc"                                                  

# Set it Locally:  HKEY_CURRENT_USER
[Environment]::SetEnvironmentVariable("PYTHONSTARTUP", 'C:\Users\<USERNAME>\.pyrc', 'User')     

# Set it Globaly: HKEY_LOCAL_MACHINE
[Environment]::SetEnvironmentVariable("PYTHONSTARTUP", 'C:\Users\<USERNAME>\.pyrc', 'Machine')  

# Set it Globaly: HKEY_LOCAL_MACHINE (also in CMD)
setx /m PYTHONSTARTUP "%HOME%\.pyrc"                                                        

享受吧!

输入图片说明


遗憾的是,在Windows上(使用“colorama”包)无法工作。还要注意的是,将“~/.pyrc”设为可执行文件并不必要,因为您不会直接从终端执行它。 - kyrill
1
因为Windows在支持ANSI颜色代码方面很糟糕,所以你的情况可能会有所不同。这取决于控制台的特定事项、您的PowerShell版本、Windows版本以及Python版本(本机Windows、Cygwin、WSL)。话虽如此,对我来说,colorama从未在不同的Python版本中按预期工作过。因此,请尝试使用自己的ANSI代码。上面的代码是针对支持TRUECOLOR的终端的,据我所知。还可以尝试使用ConEmu - not2qubit
1
当我在代码中使用print或者写入到标准输出时,Colorama在Windows上运行良好。问题只出现在sys.ps1上 - 由于某种原因,即使我用AnsiToWin32包装器替换了sys.stdinsys.__stdin__,它仍然会将转义字符打印到终端上。我认为CPython交互式解释器写入ps1的流在启动时被硬编码或保存,并忽略后来对sys.stdout的更改。 - kyrill
1
由于在Windows下的转义序列问题,我已经更新了答案,包括正确的RL_PROMPT_START_IGNORE(\x01)和RL_PROMPT_END_IGNORE(\x02)特殊序列,由readline使用,以跟踪包含转义序列的字符串长度。解决方案的详细信息可以在这里找到。 - not2qubit

2
如果您使用的是Windows(cmd.exe),并且想要一个带颜色的提示符,可以使用colorama,但有一些注意事项。如果在PYTHONSTARTUP中调用colorama.init并将包含着色转义代码的字符串分配给sys.ps1,它将无法正常工作。然而,当您使用包含着色转义代码的字符串调用print时,彩色输出确实有效。
幸运的是,设计sys.ps1的Python开发人员足够慷慨(或聪明?),让您可以使用任何对象作为ps1,而不仅仅是字符串。然后会使用其__str__方法将指定的对象转换为字符串。这意味着您可以定义自己的类,例如Prompt,并在其__str__方法中执行任何操作,包括写入已经使用colorama封装的stdout(这将起作用!)。然后只需返回空字符串即可。
这个事实给您带来了一个很好的奖励——您还可以使用非常量提示符。您想在Python shell中像bash一样显示日期吗?没问题。
import sys
import datetime
import colorama

colorama.init(autoreset=True)

class Prompt:
  def __str__(self):
    print(self.prompt, end='')
    return ''

class PS1(Prompt):

  @property
  def prompt(self):
    return '{brace_c}[{time_c}{time}{brace_c}]{prompt_c}>>> '.format(
              brace_c  = colorama.Fore.BLACK + colorama.Style.BRIGHT,
              # style is preserved, so the following are also bright:
              prompt_c = colorama.Fore.LIGHTYELLOW_EX,
              time_c   = colorama.Fore.BLACK,
              time     = datetime.datetime.now().strftime('%H:%M'),
            )

sys.ps1 = PS1()

尽管这样做完全可以,但这是一种相当hacky的方式,因为__str__方法的预期目的是返回一个str实例。因此,当您使用sys.ps2进行相同的操作时,它会出现问题。Python解释器希望__str__方法没有副作用,并且在打印PS1时显然评估了str(sys.ps1)str(sys.ps2)两者,而在打印PS2时,则使用已经评估(并保存)的str(sys.ps2)值。结果是,如果您创建与上面的PS1类似的PS2类,则应该只看到PS1,但您将同时看到PS1和PS2,并且在应该看到PS2时什么也看不到。另一个这种方法效果不佳的情况是多个线程/进程正在写入控制台。然后,来自几个线程的输出被交错,虽然这也可能发生在正常的PS1中,但这种hack使情况变得更糟。

screenshot

在这个简单的例子中,情况还不算太糟糕(没有交错,只有颜色混乱),但如果你把时间掌握得“恰当”,情况会更糟。

不错!但请添加一张截图,这样我们就可以更好地理解它的外观。你遇到的交错问题可能是缓冲问题。Python 解释器喜欢缓冲输出,所以您应该确保任何打印的内容都是无缓冲的。 - not2qubit
从图片上看,您激活的颜色在使用后没有被禁用。请确保在选择和打印颜色后,也提供ANSI序列以禁用该颜色。 - not2qubit
我不确定你的意思。我使用colorama.init(autoreset=True),所以没有必要禁用颜色。正如您在屏幕截图中看到的那样,我在终端中编写的文本(例如from threading import Thread)是白色的,这是我的正常文本颜色。启动线程写入的文本test也是白色的。问题在于括号关闭之前的提示部分应该不是白色,但它却是白色的。因此,问题实际上是颜色没有被启用,而不是被禁用了。 - kyrill
我想说的是,你可能需要将style重新设置为NORMALRESET_ALL。而且由于你正在使用线程,你可能需要在其他地方提前定义这些(例如brace_c等)项。当你不再使用它们时,为什么还要定义它们呢? - not2qubit
另外,请添加如何实现上述脚本的说明。它应该放在哪里?如何执行它? - not2qubit
你可能需要在创建提示之前先发出 RESET_ALL,因为你不知道线程函数如何处理非 ASCII 字符。 - not2qubit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接