2011-06-01 66 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)