程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

向 Python 终端输出添加颜色:完整指南

hfteth 2025-01-17 11:49:49 技术文章 12 ℃


Python Print Colored 的细分

有没有盯着一堵墙的单色终端文本,希望你能突出重要信息?让我们看看如何为 Python 终端输出添加颜色 — 它比您想象的要简单,并且可以使您的程序更加用户友好。

基础知识:ANSI 转义码

在 Python 中添加颜色最直接的方法是使用 ANSI 转义码。这些是告诉您的终端更改文本颜色的特殊序列:

# Basic color codes
RED = '\033[91m'
GREEN = '\033[92m'
BLUE = '\033[94m'
RESET = '\033[0m'  # This resets the color back to default

# Simple example
print(f"{RED}Error: File not found{RESET}")
print(f"{GREEN}Success: Data saved{RESET}")
print(f"{BLUE}Info: Processing...{RESET}")

让我们分解一下这里发生的事情:
- '\033' 是转义字符
- '[' 和 'm' 之间的数字定义颜色
- 我们总是在彩色文本后使用 'RESET' 以防止颜色渗入后续输出

创建 Color Helper 类

以下是处理彩色输出的更结构化的方法:

class Colors:
    def __init__(self):
        # Regular colors
        self.red = '\033[91m'
        self.green = '\033[92m'
        self.blue = '\033[94m'
        self.yellow = '\033[93m'
        self.magenta = '\033[95m'
        self.cyan = '\033[96m'
        self.white = '\033[97m'
        self.reset = '\033[0m'
    
    def colorize(self, text, color):
        """Add color to text and handle reset automatically"""
        color_code = getattr(self, color.lower(), '')
        return f"{color_code}{text}{self.reset}"

# Create an instance
colors = Colors()

# Usage examples
print(colors.colorize("Warning: Low disk space", "yellow"))
print(colors.colorize("Error: Connection failed", "red"))
print(colors.colorize("Success: Test passed", "green"))

此类使管理颜色变得更加容易,并防止您在使用后忘记重置颜色。

实际示例:进度更新

以下是在文件处理脚本中使用颜色创建清晰的进度更新的方法:

import time
from random import randint

def process_files(file_list):
    colors = Colors()  # Using our earlier Colors class
    
    for i, file in enumerate(file_list, 1):
        # Simulate processing
        time.sleep(0.5)
        success = randint(0, 10) > 1  # 90% success rate
        
        # Create status message
        status = f"Processing file {i}/{len(file_list)}: {file}"
        
        if success:
            print(colors.colorize(f"✓ {status}", "green"))
        else:
            print(colors.colorize(f"✗ {status} - Failed", "red"))
            
        # Add processing details in a different color
        details = f"  → Size: {randint(100, 1000)}KB"
        print(colors.colorize(details, "cyan"))

# Example usage
files = ["document.pdf", "image.jpg", "data.csv"]
process_files(files)

此脚本创建清晰的视觉层次结构:
- 绿色对号 (✓) 表示操作成功
- 红色 X 标记 (✗) 表示失败
- 青色详细信息,了解更多信息

使日志级别脱颖而出

这是一个实用的日志记录系统,它使用颜色来区分不同类型的消息:

from datetime import datetime

class ColorLogger:
    def __init__(self):
        self.colors = Colors()  # Our color helper class
        
    def _log(self, level, message, color):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        colored_level = self.colors.colorize(f"[{level}]", color)
        print(f"{timestamp} {colored_level} {message}")
    
    def info(self, message):
        self._log("INFO", message, "blue")
        
    def success(self, message):
        self._log("SUCCESS", message, "green")
        
    def warning(self, message):
        self._log("WARNING", message, "yellow")
        
    def error(self, message):
        self._log("ERROR", message, "red")

# Example usage
logger = ColorLogger()

logger.info("Starting application...")
logger.success("Database connection established")
logger.warning("Cache miss, regenerating data")
logger.error("Failed to send email")

该记录器可创建一致的颜色编码输出,使您可以轻松地一目了然地发现不同类型的消息。

高级格式设置:文本样式

除了颜色之外,ANSI 代码还可以添加文本样式:

class TextStyle:
    def __init__(self):
        # Text styles
        self.bold = '\033[1m'
        self.underline = '\033[4m'
        self.reversed = '\033[7m'
        self.reset = '\033[0m'
        
        # Colors from our previous class
        self.colors = Colors()
    
    def format(self, text, color=None, bold=False, underline=False, reverse=False):
        """Apply multiple text styles at once"""
        style = ''
        if bold:
            style += self.bold
        if underline:
            style += self.underline
        if reverse:
            style += self.reversed
        if color:
            style += getattr(self.colors, color.lower(), '')
            
        return f"{style}{text}{self.reset}"

# Example usage
style = TextStyle()

# Create styled headers
print(style.format("SYSTEM STATUS", "blue", bold=True, underline=True))
print(style.format("Critical Error", "red", bold=True))
print(style.format("New Update Available", "green", reverse=True))

这为您提供了更多选项,以便以不同的方式使文本突出显示:
- 重要信息以粗体显示
- 标题的下划线
- 反转(背景颜色)用于特殊通知

跨平台颜色支持

并非所有端子都以相同的方式处理 ANSI 颜色。以下是编写可在任何地方使用的代码的方法:

import os
import platform

class ColorSupport:
    def __init__(self):
        # Check if the terminal supports colors
        self.has_colors = self._check_color_support()
        
        # Store color codes
        self.colors = {
            'red': '\033[91m' if self.has_colors else '',
            'green': '\033[92m' if self.has_colors else '',
            'yellow': '\033[93m' if self.has_colors else '',
            'reset': '\033[0m' if self.has_colors else ''
        }
    
    def _check_color_support(self):
        """Check if the current terminal supports colors"""
        # Force colors if FORCE_COLOR env variable is set
        if os.getenv('FORCE_COLOR'):
            return True
            
        # Check platform-specific support
        if platform.system() == 'Windows':
            return self._enable_windows_color()
        
        # Most Unix-like systems support colors
        return os.getenv('TERM') not in ('dumb', '')
    
    def _enable_windows_color(self):
        """Enable color support on Windows"""
        try:
            import ctypes
            kernel32 = ctypes.windll.kernel32
            kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
            return True
        except:
            return False
    
    def colorize(self, text, color):
        """Add color if supported, otherwise return plain text"""
        if not self.has_colors:
            return text
        return f"{self.colors[color]}{text}{self.colors['reset']}"

# Example usage
cs = ColorSupport()
print(cs.colorize("This text might be red", "red"))

使用颜色构建进度条

下面是一个有用的进度条,可有效使用颜色:

import sys
import time

class ColorProgressBar:
    def __init__(self, total, width=50):
        self.total = total
        self.width = width
        self.colors = ColorSupport()
    
    def update(self, current):
        """Update progress bar"""
        # Calculate progress
        progress = current / self.total
        filled = int(self.width * progress)
        empty = self.width - filled
        
        # Choose color based on progress
        if progress < 0.3:
            color = 'red'
        elif progress < 0.7:
            color = 'yellow'
        else:
            color = 'green'
        
        # Create the progress bar
        bar = '█' * filled + '░' * empty
        percentage = int(progress * 100)
        
        # Create the full progress line
        line = f'\rProgress: [{self.colors.colorize(bar, color)}] {percentage}%'
        
        # Print and flush
        sys.stdout.write(line)
        sys.stdout.flush()

# Example usage
def process_items(items):
    progress = ColorProgressBar(len(items))
    for i, item in enumerate(items):
        progress.update(i + 1)
        time.sleep(0.1)  # Simulate work
    print()  # New line after completion

# Test it out
items = list(range(50))
process_items(items)

创建颜色增强的调试输出系统

下面是一个更高级的调试系统,它使用颜色使输出更易于阅读:

import inspect
from datetime import datetime

class DebugOutput:
    def __init__(self):
        self.colors = ColorSupport()
        self.indent_level = 0
        
    def _get_caller_info(self):
        """Get information about the calling function"""
        frame = inspect.currentframe().f_back.f_back
        filename = frame.f_code.co_filename
        lineno = frame.f_lineno
        func_name = frame.f_code.co_name
        return filename, lineno, func_name
    
    def _format_value(self, value):
        """Format different types of values with appropriate colors"""
        if isinstance(value, str):
            return self.colors.colorize(f"'{value}'", "green")
        elif isinstance(value, (int, float)):
            return self.colors.colorize(str(value), "yellow")
        elif isinstance(value, bool):
            return self.colors.colorize(str(value), "red")
        elif value is None:
            return self.colors.colorize("None", "red")
        return str(value)
    
    def debug(self, *args, **kwargs):
        """Print debug information with colors and formatting"""
        timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        filename, lineno, func_name = self._get_caller_info()
        
        # Format location info
        location = f"{filename}:{lineno} in {func_name}()"
        header = self.colors.colorize(f"[DEBUG {timestamp}]", "yellow")
        
        # Format arguments
        arg_strings = [self._format_value(arg) for arg in args]
        kwarg_strings = [
            f"{k}={self._format_value(v)}" for k, v in kwargs.items()
        ]
        all_args = arg_strings + kwarg_strings
        
        # Create indented output
        indent = "  " * self.indent_level
        
        # Print everything
        print(f"{indent}{header} {location}")
        if all_args:
            print(f"{indent}  Values:", ", ".join(all_args))

# Example usage
debug = DebugOutput()

def calculate_total(items, tax_rate=0.1):
    debug.debug("Starting calculation", items=items, tax_rate=tax_rate)
    
    subtotal = sum(items)
    debug.debug("Calculated subtotal", subtotal)
    
    tax = subtotal * tax_rate
    debug.debug("Calculated tax", tax)
    
    total = subtotal + tax
    debug.debug("Final total", total)
    
    return total

# Test the debug output
prices = [10.99, 24.99, 5.99]
total = calculate_total(prices, tax_rate=0.15)

带颜色的交互式菜单系统

以下是使用颜色创建交互式菜单的实际示例:

import sys
from typing import Dict, Callable

class ColorMenu:
    def __init__(self):
        self.colors = ColorSupport()
        self.options: Dict[str, Callable] = {}
    
    def add_option(self, key: str, description: str, action: Callable):
        """Add a menu option"""
        self.options[key] = {
            'description': description,
            'action': action
        }
    
    def display(self):
        """Show the menu with colors"""
        print(self.colors.colorize("\n=== Main Menu ===", "yellow"))
        
        for key, option in self.options.items():
            key_display = self.colors.colorize(f"[{key}]", "green")
            print(f"{key_display} {option['description']}")
        
        print(self.colors.colorize("[q] Quit", "red"))
    
    def run(self):
        """Run the interactive menu"""
        while True:
            self.display()
            choice = input("\nEnter your choice: ").lower()
            
            if choice == 'q':
                print(self.colors.colorize("Goodbye!", "yellow"))
                sys.exit(0)
            
            if choice in self.options:
                print(self.colors.colorize("\nExecuting command...", "green"))
                try:
                    self.options[choice]['action']()
                except Exception as e:
                    print(self.colors.colorize(f"Error: {e}", "red"))
            else:
                print(self.colors.colorize("Invalid option!", "red"))

# Example usage
def view_records():
    print("Viewing all records...")

def add_record():
    print("Adding new record...")

def delete_record():
    print("Deleting record...")

# Create and run the menu
menu = ColorMenu()
menu.add_option('v', "View Records", view_records)
menu.add_option('a', "Add Record", add_record)
menu.add_option('d', "Delete Record", delete_record)

# Run the menu (commented out to avoid blocking)
# menu.run()

这些示例展示了 color 如何使您的 Python 程序更加用户友好且更易于调试。关键是有目的地使用颜色来突出重要信息并在您的输出中创建清晰的视觉层次结构。

请记住:虽然颜色可以使您的输出更具可读性,但它们应该增强您呈现的信息,而不是分散注意力。始终在不同的终端环境中测试您的彩色输出,以确保其按预期工作。

最近发表
标签列表