2011-06-01 70 views
4

我如何装饰功能,使任何它打印到stdout绿色和任何它打印到stderr红色?我有termcolor模块可用。(蟒蛇)彩色印刷

Bonus karma:如何将参数传递给装饰者以指定颜色,并将它们默认为红色和绿色?

+0

装饰影响的装饰功能,不能完全不相关的功能,如'sys.stdout.write'。定义'write_to_stdout(line,color = green)'并使用它来代替'print'会容易得多。你可以在一个函数内部替换stdout,但是这看起来非常黑客并且与线程断开。 – 2011-06-01 03:40:54

+1

@Jochen:无论stdout是否被覆盖,从多个线程打印到同一个流,都会导致输出混乱,因此它是无关紧要的,创建一个特殊的write_to_stdout()函数并不能解决Python(Python )从你的脚本调用库打印到标准输出。至于hackiness,每次使用管道时都会重定向标准输出。这是一个非常正常的方法。 – 2011-06-01 04:14:26

回答

2

一个有趣的问题对我的作品在猛砸。最简单的解决方案与Pete的建议类似。在将函数运行到stderr和stdout之前,只需打印转义码即可。但是,如果stderr和stdout都通过同一个终端进行传输,它们将会发生干扰。

所以,另一种解决方案是用一个小封装器来为stdout和stderr打补丁,这样可以在每次写入期间启用颜色,只有当我们处于终端中(而不是管道) 。

#!/usr/bin/python2 

import sys 

def colorize(stdoutColor, stderrColor): 
    defaultColor = '\033[0;0m' 

    def applyColorize(f): 
    class colorWrapper(object): 
     def __init__(self, wrapee, color): 
     self.wrapee = wrapee 
     self.color = color 
     def __getattr__(self, attr): 
     if attr == 'write' and self.wrapee.isatty(): 
      return lambda x: self.wrapee.write(self.color + x + defaultColor) 
     else: 
      return getattr(self.wrapee, attr) 

    def wrapper(*args, **kwds): 
     oldStdout = sys.stdout 
     oldStderr = sys.stderr 
     sys.stdout = colorWrapper(oldStdout, stdoutColor) 
     sys.stderr = colorWrapper(oldStderr, stderrColor) 
     try: 
     f(*args, **kwds) 
     finally: 
     sys.stdout = oldStdout 
     sys.stderr = oldStderr 

    return wrapper 

    return applyColorize 


greenColor = '\033[01;32m' 
redColor = '\033[01;31m' 

def foo(): 
    print "I'm ordinary and boring!" 
    print >> sys.stderr, 'Writing to stderr!' 

@colorize(greenColor, redColor) 
def colorFoo(): 
    print "I'm colorful and exciting!" 
    print >> sys.stderr, 'Writing to stderr!' 

if __name__ == '__main__': 
    foo() 
    colorFoo() 
    foo() 

这还是可以打磨了一点,但它应该正确后本身做在大多数情况下工作和清理。当然,请记住我正在使用特定于shell的转义码。如果您需要便携性,则必须将呼叫转义码替换为便携式终端控制模块。

0

这在我的Mac的Terminal.app

import sys 
green = '\033[01;32m' 
red = '\033[01;31m' 

sys.stdout.write(green+"Hello ") 
sys.stderr.write(red+"world!") 
+2

你不需要使用后缀吗?当你这样做时,所有终端输出保持绿色或红色 – 2012-11-06 07:34:11

0

这里是我的代码以termcolor模块:

from termcolor import colored 

class ColoredOutput: 
    def __init__(self, org_handle, color, on_color=None, attrs=['bold']): 
     self.org_handle = org_handle 
     def wrapper_write(x): 
      return org_handle.write(colored(x, color=color, on_color=on_color, attrs=attrs)) 
     self.wrapper_write = wrapper_write 
    def __getattr__(self, attr): 
     return self.wrapper_write if attr == 'write' else getattr(self.org_handle, attr) 

if __name__ == '__main__': 
    import sys 
    import colorama # I'm working under windows 7, so i need this module to enable terminal color 

    colorama.init() 
    sys.stderr = ColoredOutput(sys.stderr, 'red') 
    print('This is a test string', file=sys.stderr)