You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PYTHONSTARTUP配置多行Python交互式提示符sys.ps1以避免重复输出问题

如何通过PYTHONSTARTUP配置多行Python交互式提示符sys.ps1以避免重复输出问题

我完全理解你遇到的麻烦——想在Python交互提示符里搞个多行样式,第一行显示路径和时间,第二行是输入提示符,但不管是直接用多行字符串还是带__repr__的类,要么输入时第一行被反复覆盖,要么每打一个字符就重复刷第一行,简直头疼!

咱们先扒一扒为啥之前的方法不管用:

  1. 直接设置多行sys.ps1:Windows CMD里的Python交互环境没有像Unix那样的readline支持,每次输入字符时终端会重新渲染整个提示符,导致第一行被反复打印覆盖。
  2. 带__repr__的类:你的__repr__里用了print,而Python在输入过程中(尤其是CMD环境)会频繁调用sys.ps1的生成逻辑,每输入一个字符就触发一次__repr__,自然会反复打印第一行。

可行的解决方案

核心思路是:只在命令执行完成后才打印第一行的路径和时间,输入过程中绝不重复打印。我们可以用一个标志位来区分「新命令开始」和「正在输入」的状态,再配合重写Python的displayhook和excepthook来控制这个标志位。

把你原来的代码改成下面这样:

import sys
import datetime
import os
import ctypes
from BlurWindow.blurWindow import GlobalBlur as gb__

# 保留你原有的窗口模糊设置
gb__(ctypes.windll.user32.GetForegroundWindow(), '#000000CC', True, True)

# ANSI颜色控制码(保留你的定义)
c__ = "\033[38;5;"
e__ = "\033[m"

# 二级提示符(保留你的设置)
sys.ps2 = f"{c__}125m... {e__}"

# 判断是否为管理员(保留你的逻辑)
is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
prompt_char = "#" if is_admin else ">"

# 标志位:标记是否是新命令的起始状态
new_command = True

class DynamicPS1:
    def __repr__(self):
        global new_command
        if new_command:
            # 仅在新命令开始时打印路径和时间
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            current_path = os.path.abspath(os.getcwd())
            # 用sys.stdout.write+flush确保输出立即生效,避免缓冲问题
            sys.stdout.write(f"{c__}208m{current_path} {c__}106m{current_time}{e__}\n")
            sys.stdout.flush()
            # 切换状态:输入过程中不再打印第一行
            new_command = False
        # 返回第二行的输入提示符
        return f"{c__}125mPY{prompt_char} {e__}"

sys.ps1 = DynamicPS1()

# 重写displayhook:命令执行完成后,重置标志位为新命令状态
original_displayhook = sys.displayhook
def custom_displayhook(value):
    global new_command
    original_displayhook(value)
    new_command = True

sys.displayhook = custom_displayhook

# 重写excepthook:处理Ctrl+C或异常情况,确保标志位正确重置
original_excepthook = sys.excepthook
def custom_excepthook(type, value, traceback):
    global new_command
    original_excepthook(type, value, traceback)
    new_command = True

sys.excepthook = custom_excepthook

代码工作原理

  1. 标志位控制:new_command 变量用来判断是否需要打印第一行信息,只有在上一条命令执行完成(或刚进入交互环境)时才会打印。
  2. displayhook重写:Python执行完每条命令后都会调用displayhook,我们在这里把标志位重置为True,为下一条命令的提示符做准备。
  3. excepthook重写:处理用户按Ctrl+C或命令抛出异常的情况,确保标志位被正确重置,不会影响下一次提示符的显示。
  4. 直接写标准输出:用sys.stdout.write代替print,并手动调用flush,避免输出缓冲导致的显示延迟或错位。

这样修改后,你就能得到想要的效果:

  • 执行完命令后,自动打印最新的路径和时间,然后显示输入提示符
  • 输入字符时,不会重复打印第一行信息,光标正常在提示符后移动
  • 按Ctrl+C或命令报错后,下一次提示符依然会正确显示路径和时间

备注:内容来源于stack exchange,提问作者AnikeiPS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:43:08