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
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"
}
Che operativo/terminale stai usando a proposito? –
linux, domanda ora risolta, grazie comunque! – Nicholas