简体   繁体   English

(python) 在 function 中使用装饰器进行彩色打印

[英](python) colour printing with decorator in a function

How can I decorate a function so that anything it prints to stdout is in green and anything it prints to stderr is in red ?如何装饰 function 使其打印到stdout的任何内容为绿色,打印到stderr的任何内容为红色 I have the termcolor module available.我有可用的termcolor模块。

Bonus karma : How can I pass arguments to the decorator to specify the colours, defaulting them to red and green?额外的业力:如何将 arguments 传递给装饰器以指定颜色,默认为红色和绿色?

An interesting question.一个有趣的问题。 The simplest solution would be similar to what Pete suggest.最简单的解决方案类似于 Pete 的建议。 Just print the escape codes before running the function to each of stderr and stdout.只需在运行 function 到每个标准错误和标准输出之前打印转义码。 However, if both stderr and stdout feed the same terminal, as is usually the case, they will interfere.但是,如果 stderr 和 stdout 都输入同一个终端,通常情况下,它们会干扰。

So, an alternative solution is to monkey-patch stdout and stderr with a tiny wrapper that enables the color for the duration of each write, taking care to do this only if we're in a terminal (and not piped).因此,另一种解决方案是使用一个微型包装器对标准输出和标准错误进行猴子补丁,该包装器在每次写入期间启用颜色,仅当我们在终端中(而不是管道)时才注意这样做。

#!/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()

This can still be polished a bit, but it should do the job in most cases and cleans up after itself properly.这仍然可以稍微完善一下,但在大多数情况下它应该可以完成这项工作,并且可以自行清理。 Of course, keep in mind I'm using shell-specific escape codes.当然,请记住我使用的是特定于 shell 的转义码。 If you want portability, you'll have to replace the escape code writes with calls to a portable terminal control module.如果您想要可移植性,则必须将转义代码写入替换为对便携式终端控制模块的调用。

Here is my code with termcolor module:这是我使用 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)

This works for me in Bash in my Mac's Terminal.app这适用于我 Mac 的 Terminal.app 中的 Bash

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM