2012-08-16 1 views
5

A quanto pare, posso farlo in Python 2.7:stringa di byte letterale con caratteri non-ASCII

value = '國華' 

Sembra Python sta usando una codifica per codificare i caratteri della stringa letterale una stringa di byte. Cos'è quella codifica? È la codifica definita in sys.getdefaultencoding(), la codifica del file sorgente o qualcos'altro?

Grazie

+1

È la riga nel file di origine o sulla riga di comando? Inoltre, vuoi davvero imparare la complessità della codifica in Python 2.7 (che è leggermente diversa da 2.6 e 3.x), o stai solo cercando di aggirare un problema che potrebbe essere risolto attaccando un 'u' prima le virgolette? – abarnert

+0

In realtà sto cercando di imparare la complessità della codifica in Python 2.7. E questo è in un file sorgente, ma sono anche interessato a sapere se è diverso in un prompt dei comandi. – Flavien

+1

Python 2.7 dice di non farlo, ma se sei interessato a cosa fa CPython 2.7 se lo fai comunque ... i byte letterali all'interno delle virgolette nel file sorgente (ad esempio, '\ xe5 \ x9c \ x8b \ xe8 \ x8f \ xaf ') sono memorizzati come una stringa di byte. Poiché la dichiarazione di codifica del file sorgente potrebbe non essere la stessa di 'sys.getdefaultencoding()', potrebbe non esserci modo di interpretarla in modo sicuro, ma i byte ci sono. E se le due codifiche sono uguali, così come quelle del terminale, e quella codifica può gestire quei caratteri, puoi persino "stampare valore" e vedere cosa ti aspetti. È quello che vuoi, o c'è di più? – abarnert

risposta

7

getdefaultencoding ha alcuna relazione con la codifica del sorgente o del terminale. È la codifica utilizzata per convertire le stringhe di byte in modo implicito nelle stringhe Unicode e deve sempre essere 'ascii' su Python 2.X ('utf8' su Python 3.X).

su Python 2.X, la vostra linea di codice in uno script senza codifica dichiarata produce un errore:

SyntaxError: Non-ASCII character '\x87' in file ... 

Il carattere effettivamente non ASCII può variare, ma non funzionerà senza una codifica dichiarazione. Una dichiarazione di codifica è richiesta per utilizzare caratteri non ASCII su Python 2.X. La dichiarazione di codifica deve corrispondere alla codifica del file di origine. Ad esempio:

# coding: utf8 
value = '國華' 

quando salvato come cp936 produce:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte 

Quando la codifica è corretta, i byte nella stringa di byte sono letteralmente ciò che è nel file sorgente, in modo che conterrà il codificato byte dei personaggi. Quando Python analizza una stringa Unicode, i byte vengono decodificati utilizzando la codifica di origine dichiarata in Unicode. Si noti la differenza quando la stampa di una stringa di byte UTF-8 e una stringa Unicode su una console cp936:

# coding: utf8 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

uscita:

鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf' 
國華 u'\u570b\u83ef' 

La stringa di byte contiene il 3-byte UTF-8 codifiche del due caratteri, ma visualizzati in modo errato poiché la sequenza di byte non è compresa da un terminale cp936. Unicode è stampato correttamente e la stringa contiene i punti di codice Unicode decodificati dai byte UTF-8 del file sorgente.

Nota la differenza quando dichiarare e utilizzare la codifica che corrisponde al terminale:

# coding: cp936 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

uscita:

國華 '\x87\xf8\xc8A' 
國華 u'\u570b\u83ef' 

Il contenuto della stringa di byte è adesso i codifiche 2 byte cp936 del due caratteri ('A' equivalente a '\ x41') e viene visualizzato correttamente poiché il terminale comprende la sequenza di byte cp936. La stringa Unicode contiene gli stessi punti di codice Unicode per i due caratteri dell'esempio precedente poiché la sequenza di byte di origine è stata decodificata utilizzando la codifica di origine dichiarata in Unicode.

Se uno script ha una corretta dichiarazione di codifica sorgente e utilizza le stringhe Unicode per il testo, esso visualizzerà i caratteri corretti indipendentemente codifica terminale . Lancia un UnicodeEncodeError se il terminale non supporta il carattere piuttosto che visualizza il carattere sbagliato.

Una nota finale: Python 2.X default encoding 'ascii' ove non dichiarato e consente di caratteri non ASCII nelle stringhe di byte se la codifica li supporta. Il default di Python 3.X è la codifica 'utf8' (quindi assicuratevi di salvare in quella codifica o dichiarate in altro modo), e non consentire caratteri non ASCII nelle stringhe di byte.

Se il carattere del terminale supporta il carattere.
Se la codifica del terminale supporta il carattere.

1
value = b'國華' 

è privo di significato (la b è implicita in Python 2.x) - perché vuoi un stringa di byte che contiene caratteri? Python riproduce semplicemente i byte in qualsiasi codifica utilizzata dal tuo terminale/editor. Ciò che si vuole è un personaggio stringa:

value = u'國華' 

In un file di codice sorgente (al contrario di una shell interattiva), non dimenticate di declare the encoding aggiungendo la seguente linea all'inizio del file:

# -*- coding: utf-8 -*- 
+0

Ben apparentemente i designer di Python non pensavano che fosse privo di significato dal momento che lo rendevano valido. Non hai davvero risposto alla mia domanda, che la codifica utilizza Python quando eseguo quella linea, come posso scoprire dal codice? – Flavien

+0

Quando si esegue tale riga nella shell interattiva o in un file di origine con una dichiarazione di codifica o ... cosa? – abarnert

+2

@I caratteri non ASCII di Flavien in letterali byte sono un artefatto storico. Non esiste un codice che li renda validi, sono accettati solo accidentalmente e risalgono al tempo in cui Python non aveva una semantica chiara della stringa di caratteri vs caratteri. I caratteri non ASCII in letterali byte non sono più validi; sono stati [rimossi da Python 3] (http://ideone.com/f1iLN). Python non usa alcuna codifica quando si esegue quella linea. Il file è una stringa di byte, così come il valore dell'oggetto byte generato dal valore letterale. – phihag