(python) цветная печать с декоратором в функции - PullRequest
4 голосов
/ 01 июня 2011

Как я могу украсить функцию так, чтобы все, что она печатает на stdout, было зеленым , а все, что она печатает на stderr, было красным ? У меня есть модуль termcolor.

Бонус карма : Как я могу передать аргументы декоратору, чтобы указать цвета, по умолчанию их красный и зеленый?

Ответы [ 3 ]

2 голосов
/ 01 июня 2011

интересный вопрос.Самое простое решение будет похоже на то, что предлагает Пит.Просто напечатайте управляющие коды перед запуском функции для каждого из 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()

Это все еще можно немного отшлифовать, но в большинстведела и убирает за собой должным образом.Конечно, имейте в виду, что я использую специфичные для оболочки escape-коды.Если вы хотите переносимости, вам придется заменить записи escape-кода вызовами на портативный модуль управления терминалом.

0 голосов
/ 28 июля 2017

Вот мой код с модулем 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)
0 голосов
/ 01 июня 2011

Это работает для меня в Bash в терминале моего Mac.app

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

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