[Python] Che barba sta codifica!

Marco Buttu marco.buttu a gmail.com
Sab 20 Giu 2015 09:39:57 CEST


On 19/06/2015 17:56, Manlio Perillo wrote:

> 2015-06-19 16:58 GMT+02:00 Diego Barrera <diegonebarrera a yahoo.it 
> <mailto:diegonebarrera a yahoo.it>>:
>
>     premesso che non ho mai capito come funziona la codifica dei
>     caratteri,
>
>
> Documentati il prima possibile.
> Ad esempio:
> http://www.joelonsoftware.com/articles/Unicode.html

Ascolta il suggerimento di Manlio ;)

La codifica dei caratteri e' il pane quotidiano di un programmatore, per 
cui se non si capisce come funziona, prima di andare avanti ci si deve 
soffermare (un pomeriggio, due, quanto basta) per studiarla e capirla 
*sino in fondo*. E' veramente un concetto imprescindibile. La 
distinzione tra testo e byte che si ha in Python 3 viene spesso 
criticata, ma credo sia uno dei suoi maggiori punti di forza, ed è una 
scelta veramente Pythonica, in perfetto accordo con lo Zen di Python.

In Python 2 poi darmi una sequenza di byte come stringa:

   >>> open('myfile', 'w').write('via 1\xf8 Maggio, 21') # Python 2

e io posso leggerla come testo, senza pormi alcun problema:

   >>> open('myfile').read() # Python 2
   'via 1\xf8 Maggio, 21'

Questo non solleva eccezioni, e per chi non sa cosa sta sotto il 
passaggio da byte a testo (che qua non avviene, perche' in Python 2 e' 
un miscuglio) e viceversa, e' il comportamento desiderato, visto che "Il 
mio programma gira, anche se ogni tanto mi saltano fuori caratteri 
strani". E infatti anche per questo abbiamo mojibake dietro ogni angolo.

In Python 3 la musica cambia. *Giustamente* i byte sono byte, e il testo 
e' testo, ovvero una sequenza di byte interpretata secondo una data 
codifica. Apro il file in lettura, e per default open() tira fuori il 
_testo_. Ma per poter ottenere testo da quella sequenza di byte, 
ovviamente deve poter sapere come interpretare tali byte. Per default 
ipotizza che voglio usare l'encoding impostato nella mia macchina (utf-8):

   >>> open('myfile').read()
   Traceback (most recent call last):
    ...
   UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf8...

Non e' utf-8. Se so cosa fare, lo faccio:

   >>> open('myfile', encoding='cp850').read() # Grazie a Carlo ;)
   'via 1° Maggio, 21'

Se non ho idea di come il testo originale e' stato codificato, e non 
voglio provare ad indovinare, posso *esplicitamente* indicare di fare 
passare gli errori silenziosamente:

   >>> open('myfile', errors='ignore').read()
   'via 1 Maggio, 21'

"Explicit is better than implicit" and "Errors should never pass silently".

Morale della favola:

* impensabile non spendere qualche pomeriggio per studiare la codifica 
dei caratteri
* byte e testo non sono la stessa cosa
* Python 3 ha scelto la soluzione piu' pythonica per gestire la cosa

-- 
Marco Buttu

INAF-Osservatorio Astronomico di Cagliari
Via della Scienza n. 5, 09047 Selargius (CA)
Phone: 070 711 80 217
Email: mbuttu a oa-cagliari.inaf.it



Maggiori informazioni sulla lista Python