2013-07-21 10 views
8

Ho sperimentato un po 'con l'output a colori nel terminale e Python 2.7.3. I codici colore ANSI sono sempre resi in modo impeccabile nel terminale, con questa piccola eccezione che non sono riuscito a individuare con precisione rispetto a questa particolare definizione del dizionario.Python: il carattere di escape ottale 033 da un valore di dizionario si traduce in un'istruzione di stampa in un carattere UTF-8 invece

Ecco cosa provoca confusione:

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) 

L'uscita per 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'} 

Questo mi sembra essere la traduzione corretta in formato esadecimale. Nonostante ciò, i valori del dizionario non vengono trasmessi correttamente all'istruzione print. Né i modificatori letterali raw né quelli Unicode (fuori dalla disperazione) cambiano nulla. Devo mancare qualcosa di piuttosto ovvio. Sui terminali senza supporto UTF-8, il carattere Unicode viene omesso.

Ho visto le implementazioni per 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:

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)) 

E un paio di altri. Analiticamente, tutti evitano di definire l'intera sequenza nel dizionario. Sono d'accordo sul fatto che un simile approccio sia lessicalmente ragionevole. Resta il fatto che il carattere di escape da un valore di dizionario non è interpretato correttamente, a parte, ad esempio, in un hash Perl, C++ vector ized map <string, string> o C struct (se simile a una mappa) char *string.

E questo porta alla domanda: C'è una ragione particolare, secondo lo standard, se possibile, sul motivo per cui il dizionario (diciamolo così :) l'interpolazione devia da una stringa semplice?


Ecco il fisso codice colore dict (scheda-indentated se editing, strisce in modo apparentemente i caratteri di tabulazione per la lettura):

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" 
} 
+0

Che operativo/terminale stai usando a proposito? –

+0

linux, domanda ora risolta, grazie comunque! – Nicholas

risposta

7

ho attraversato il codice sorgente e penso che il probelm è con la definizione del colore all'interno del dizionario.

Se si osserva attentamente, il valore del dizionario per un colore è qualcosa come \ 033 [1,30m per il colore bianco. Tuttavia dovrebbe essere \ 033 [1; 30m. Si noti che si sta utilizzando un carattere ', (virgola) anziché' ; (punto e virgola) carattere. Come test ho creato un sottoinsieme del dizionario dei colori e ho eseguito questi test.

>>> 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 
>>> 

Spero che questo aiuti il ​​sistema

+0

Questo è probabilmente il problema, il [ANSI escape codes for color] (http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) usa un separatore di punto e virgola. – martineau

+0

Oh amico, grazie mille per aver avuto la pazienza e guardare così accuratamente il mio pezzo di codice. Avevo incollato questa parte da un altro script perl e ho fatto una brutta copia regex in vim. Grazie ancora per la vostra attenzione! – Nicholas