La codifica ASCII include solo i byte con valori <= 127
. L'intervallo di caratteri rappresentati da questi byte è identico nella maggior parte delle codifiche; in altre parole, "A" è chr(65)
in ASCII, in latin-1, in UTF-8 e così via.
Il simbolo a metà, tuttavia, non fa parte del set di caratteri ASCII, quindi quando Python prova a codificare questo simbolo in ASCII, non può fare altro che fallire.
Aggiornamento: Ecco cosa succede (presumo stiamo parlando CPython):
float(u'\xbd')
porta a PyFloat_FromString
in floatobject.c essere chiamato. Questa funzione, dando un oggetto unicode, a sua volta chiama lo PyUnicode_EncodeDecimal
in unicodeobject.c. Da sfogliare il codice, capisco che questa funzione trasforma l'oggetto Unicode in una stringa sostituendo ogni carattere con un punto di codice unicode <256
con il byte di quel valore, cioè il carattere a metà, con il punto di codice 189, viene trasformato in chr(89)
.
Quindi, PyFloat_FromString
funziona come al solito. In questo momento sta funzionando con una stringa normale, che sembra contenere un byte di intervallo non ASCII. Non gli importa di questo; trova solo un byte che non è una cifra, un punto o simili, quindi solleva l'errore di valore.
L'argomento di questa eccezione è una stringa
"invalid literal for float(): " + evil_string
va bene; un messaggio di eccezione è, dopo tutto, una stringa. È solo quando si tenta di decodificare questa stringa, utilizzando la codifica ASCII predefinita, che questo si trasforma in un problema.
Questo dovrebbe essere considerato un bug in Python? Il mio ragionamento: se float() ha ricevuto una stringa Unicode, dovrebbe generare un'eccezione descritta in Unicode se il messaggio includerà l'input. Altrimenti, le eccezioni non possono essere gestite in sicurezza, come mostra l'esempio. – pablobm
Penso che chiamare un bug sia corretto - l'errore messaggioeg probabilmente dovrebbe contenere 'repr (v)' invece di 'str (s)', poiché conoscere il valore di input originale è più utile della versione con codifica decimale. –