简体   繁体   English

Python:字典值中的八进制转义字符\\ 033将print语句转换为UTF-8字符

[英]Python: octal escape character \033 from a dictionary value translates in a print statement to a UTF-8 character instead

I've been experimenting a little with color output in terminal and Python 2.7.3 . 我一直在终端和Python 2.7.3中尝试一些颜色输出。 The ANSI color codes are always rendered flawlessly in the terminal, with this one little exception which I couldn't pinpoint yet any preciser than to this particular dictionary definition. ANSI颜色代码总是在终端中完美呈现,有一个小例外,我无法确定任何精简程序,而不是这个特定的字典定义。

Here's what causes confusion: 这是导致混淆的原因:

color = {
    'white':    "\033[1,37m",
    'yellow':   "\033[1,33m",
    'green':    "\033[1,32m",
    'blue':     "\033[1,34m",
    'cyan':     "\033[1,36m",
    'red':      "\033[1,31m",
    'magenta':  "\033[1,35m",
    'black':    "\033[1,30m",
    'darkwhite':  "\033[0,37m",
    'darkyellow': "\033[0,33m",
    'darkgreen':  "\033[0,32m",
    'darkblue':   "\033[0,34m",
    'darkcyan':   "\033[0,36m",
    'darkred':    "\033[0,31m",
    'darkmagenta':"\033[0,35m",
    'darkblack':  "\033[0,30m",
    'off':        "\033[0,0m"
}

yellow = "\033[1;33m"
off = "\033[0;0m"

print color['yellow'] + "string to render" + color['off']     # fails to render properly
print "%(yellow)sstring to render%(off)s" % color             # ditto
print "%sstring to render%s" % (color['yellow'], color['off'])# ditto

print yellow + "string to render" + off                       # as intended

pp = pprint.PrettyPrinter(indent=6)
pp.pprint(color)

The output for PrettyPrinter: PrettyPrinter的输出:

{ 'black': '\x1b[1,30m',
  'blue': '\x1b[1,34m',
  'cyan': '\x1b[1,36m',
  'darkblack': '\x1b[0,30m',
  'darkblue': '\x1b[0,34m',
  'darkcyan': '\x1b[0,36m',
  'darkgreen': '\x1b[0,32m',
  'darkmagenta': '\x1b[0,35m',
  'darkred': '\x1b[0,31m',
  'darkwhite': '\x1b[0,37m',
  'darkyellow': '\x1b[0,33m',
  'green': '\x1b[1,32m',
  'magenta': '\x1b[1,35m',
  'off': '\x1b[0,0m',
  'red': '\x1b[1,31m',
  'white': '\x1b[1,37m',
  'yellow': '\x1b[1,33m'}

This seems to me to be the proper translation into hexadecimal format. 在我看来,这是正确的十六进制格式转换。 Despite this fact, the dictionary values are not passed properly to the print statement. 尽管如此,字典值仍未正确传递给print语句。 Neither the raw nor the Unicode (out of despair) string literal modifiers change anything. 原始和Unicode(绝望之外)字符串文字修饰符都不会改变任何东西。 I must be missing something rather obvious. 我必须遗漏一些相当明显的东西。 On terminals without UTF-8 support, the Unicode character is omitted. 在没有UTF-8支持的终端上,省略了Unicode字符。

I've seen the implementations for termcolor : 我见过termcolor的实现:

if os.getenv('ANSI_COLORS_DISABLED') is None:
    fmt_str = '\033[%dm%s'
    if color is not None:
        text = fmt_str % (COLORS[color], text)

    if on_color is not None:
        text = fmt_str % (HIGHLIGHTS[on_color], text)

    if attrs is not None:
        for attr in attrs:
            text = fmt_str % (ATTRIBUTES[attr], text)

    text += RESET
return text

colorama : colorama

CSI = '\033['
def code_to_chars(code):
    return CSI + str(code) + 'm'
class AnsiCodes(object):
    def __init__(self, codes):
        for name in dir(codes):
            if not name.startswith('_'):
                value = getattr(codes, name)
                setattr(self, name, code_to_chars(value))

And a couple of others. 还有其他几个。 Analytically, they all avoid defining the entire sequence in the dictionary. 从分析上讲,它们都避免在字典中定义整个序列。 I do agree that such an approach is lexically reasonable. 我确实同意这种方法在词汇上是合理的。 Yet the fact remains that the escape character from a dictionary value is not interpreted correctly, other than, say, in a Perl hash, C++'s vector ized map <string, string> , or a C's struct 's (if akin a map) char *string . 然而事实仍然是字典值中的转义字符没有被正确解释,除了比如Perl哈希,C ++的vector量化map <string, string>或C的struct (如果类似于地图) char *string

And this leads to the question: Is there a particular reason, per the standard, if possible, as to why dictionary (let's dub this:) interpolation deviates from a plain string? 这导致了一个问题: 如果可能的话,是否有一个特殊的原因,为什么字典(让我们配音这个:)插值偏离普通字符串?


Here's the fixed color code dict (tab-indentated if editing, SO seemingly strips the tab chars for reading): 这是固定颜色代码字典(如果编辑则标签缩进,SO似乎剥离标签字符以便阅读):

color = {
    'white':    "\033[1;37m",
    'yellow':   "\033[1;33m",
    'green':    "\033[1;32m",
    'blue':     "\033[1;34m",
    'cyan':     "\033[1;36m",
    'red':      "\033[1;31m",
    'magenta':  "\033[1;35m",
    'black':      "\033[1;30m",
    'darkwhite':  "\033[0;37m",
    'darkyellow': "\033[0;33m",
    'darkgreen':  "\033[0;32m",
    'darkblue':   "\033[0;34m",
    'darkcyan':   "\033[0;36m",
    'darkred':    "\033[0;31m",
    'darkmagenta':"\033[0;35m",
    'darkblack':  "\033[0;30m",
    'off':        "\033[0;0m"
}

I went through your source code and I think the probelm is with the color definition within the dictionary. 我浏览了你的源代码,我认为probelm是在字典中的颜色定义。

If you observe carefully, your dictionary value for a color is something like \\033[1,30m for white color. 如果仔细观察,颜色的字典值就像\\ 033 [白色1,30米] However it should be \\033[1;30m . 但它应该是\\ 033 [1; 30米 Note that you are using a ' ,(comma) character instead of ' ;(semicolon) character. 请注意,您使用的是' ,(逗号)字符而不是' ;(分号)字符。 As a test I created a subset of the color dictionary and ran these tests. 作为测试,我创建了颜色字典的子集并运行了这些测试。

>>> color = {'white' :'\033[1;37m', 'yellow':'\033[1;33m', 'off' : '\033[0;0m'}
>>> print color['white'] + 'string' + color['off']
string   #this string is white in color
>>> print color['yellow'] + 'string' + color['off']
string #this string is yellow in color
>>> color['yellow'] = '\033[1,33m' #incorrect color code - using a , character instead of ;
>>> print color['yellow'] + 'string' + color['off']
string   #prints the string in console default color i.e. not in yellow color
>>> 

Hope this helps 希望这可以帮助

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

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