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

Python Windows CUI应用如何在自定义函数返回后实现控制台闪烁

问题原因

你原有代码的执行顺序是先跑闪烁检测的while循环,循环完全结束后才会执行input()调用输出提示,所以提示只能在闪烁停止后展示。

解决方案

最简改法:调整执行顺序

核心思路是先手动输出输入提示并强制刷新控制台缓冲区,再执行闪烁逻辑,最后等待用户输入:

import time
import ctypes
from ctypes import windll

# 你的原有实现,此处省略具体代码
def get_foreground_window_title():
    pass

def custom_formatted_input(message: str = "") -> str:
    # 1. 先打印输入提示,不换行,flush保证内容立刻输出到控制台
    prompt = f"{time.strftime('%Y-%m-%d %H:%M:%S')}{' '.ljust(4)}[INPUT]{' '.ljust(6)}{message} "
    print(prompt, end='', flush=True)
    
    console_hwnd = windll.kernel32.GetConsoleWindow()
    # 2. 执行闪烁逻辑,直到控制台窗口被激活
    while get_foreground_window_title() != "cmd.exe":
        windll.user32.FlashWindow(console_hwnd, True)
        time.sleep(0.5)
    
    # 3. 窗口激活后等待用户输入
    return input()

装饰器实现

如果需要把闪烁逻辑抽离复用,可以用装饰器封装:

def flash_when_inactive(func):
    def wrapper(message: str = "", *args, **kwargs):
        # 先输出输入提示
        prompt = f"{time.strftime('%Y-%m-%d %H:%M:%S')}{' '.ljust(4)}[INPUT]{' '.ljust(6)}{message} "
        print(prompt, end='', flush=True)
        
        # 闪烁检测逻辑
        console_hwnd = windll.kernel32.GetConsoleWindow()
        while get_foreground_window_title() != "cmd.exe":
            windll.user32.FlashWindow(console_hwnd, True)
            time.sleep(0.5)
        
        # 执行原输入逻辑
        return func(*args, **kwargs)
    return wrapper

# 给基础输入函数加装饰器即可
@flash_when_inactive
def custom_input() -> str:
    return input()

# 调用示例
user_input = custom_input("请输入操作指令:")

优化建议:使用系统原生闪烁API

不用自己写循环控制闪烁,调用FlashWindowEx可以实现系统级的自动闪烁,直到窗口激活为止,性能更稳定:

def flash_console_until_active():
    class FLASHWINFO(ctypes.Structure):
        _fields_ = [
            ("cbSize", ctypes.c_uint),
            ("hwnd", ctypes.c_void_p),
            ("dwFlags", ctypes.c_uint),
            ("uCount", ctypes.c_uint),
            ("dwTimeout", ctypes.c_uint)
        ]
    # 0x3 = FLASHW_ALL(同时闪烁标题栏和任务栏),0xC = FLASHW_TIMERNOFG(直到窗口激活才停止)
    FLASH_FLAGS = 0x3 | 0xC
    console_hwnd = windll.kernel32.GetConsoleWindow()
    fw = FLASHWINFO(
        cbSize=ctypes.sizeof(FLASHWINFO),
        hwnd=console_hwnd,
        dwFlags=FLASH_FLAGS,
        uCount=0, # 0代表无限闪烁直到激活
        dwTimeout=500 # 闪烁间隔500ms
    )
    windll.user32.FlashWindowEx(ctypes.byref(fw))

使用这个API之后可以去掉手动写的while闪烁循环,代码更简洁。

内容的提问来源于stack exchange,提问作者user16667377

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:54:03