2009-04-07 7 views

risposta

55

Penso che sia semplice come non prima la conversione in ASCII.

>>> print u'exámple'.upper() 
EXÁMPLE 
+1

se faccio s = 'exámñple', come posso stampare correttamente in maiuscolo? –

+0

Voglio dire, come posso convertire s in unicode senza questo errore UnicodeDecodeError: 'ascii' può 'decodificare il byte 0xa0 in posizione 2 (Stavo usando u' '+ s) –

+2

Questa è un'altra domanda, ma tu devi impostare sysencoding su utf.Dai un'occhiata qui: http://stackoverflow.com/questions/5419/python-unicode-and-the-windows-console/8020#8020 –

17

In python 2.x, basta convertire la stringa in unicode prima di chiamare upper(). Utilizzando il codice, che è in formato UTF-8 su questo Web:

>>> s = 'exámple' 
>>> s 
'ex\xc3\xa1mple' # my terminal is not utf8. c3a1 is the UTF-8 hex for á 
>>> s.decode('utf-8').upper() 
u'EX\xc1MPLE' # c1 is the utf-16 aka unicode for á 

La chiamata a decode prende dal suo formato attuale in Unicode. Puoi quindi convertirlo in un altro formato, come utf-8, usando la codifica. Se il personaggio fosse, per esempio, iso-8859-2 (ceco, ecc., In questo caso), dovresti invece usare s.decode('iso-8859-2').upper().

Come nel mio caso, se il terminale non è unicode/utf-8 compatibile, il meglio che si possa sperare è una rappresentazione esadecimale dei caratteri (come il mio) o convertirlo in modo smodato usando s.decode('utf-8').upper().encode('ascii', 'replace'), che si traduce in 'EX? Mple'. Se non riesci a mostrare il tuo terminale come unicode, scrivi l'output in un file in formato utf-8 e aprilo nel tuo editor preferito.

4

Penso che ci sia un po 'di background ci manca qui:

>>> type('hello') 
<type 'str'> 

>>> type(u'hello') 
<type 'unicode'> 

Finché si sta utilizzando "Unicode" stringhe invece di stringhe "nativi", gli operatori come superiore() opereranno con unicode in mente. FWIW, Python 3 utilizza unicode per impostazione predefinita, rendendo la distinzione largamente irrilevante.

Facendo una stringa di unicode-str e poi di nuovo a unicode è ottimale in molti modi, e molte biblioteche produrrà uscita unicode se lo vuoi; quindi prova ad usare solo gli oggetti unicode per le stringhe internamente ogni volta che puoi.

8

prima di tutto, uso solo python 3.1 in questi giorni; il suo merito centrale è quello di avere stringhe di byte disambiguated da oggetti unicode. questo rende la stragrande maggioranza delle manipolazioni del testo molto più sicure del solito. pesando i trilioni di domande degli utenti riguardanti i problemi di codifica di python 2.x, la convenzione u'äbc di python 2.1 era solo un errore; con esplicito bytes e bytearray, la vita diventa molto più facile.

in secondo luogo, se py3k non è il vostro gusto, quindi provare ad andare con from __future__ import unicode_literals, in quanto questo imiterà il comportamento di py3k su Python 2.6 e 2.7. questa cosa avrebbe evitato l'errore (facilmente commesso) che hai fatto quando hai detto print 'exámple'.upper(). essenzialmente, questo è lo stesso di py3k: print('exámple'.encode('utf-8').upper()).confrontare queste versioni (per py3k):

print('exámple'.encode('utf-8').upper()) 
print('exámple'.encode('utf-8').upper().decode('utf-8')) 
print('exámple'.upper()) 

Il primo è, in fondo, quello che hai fatto quando usato una corda nuda 'exámple', a patto di impostare la codifica predefinita per utf-8 (secondo un pronunciamento BDFL, l'impostazione di default la codifica in fase di esecuzione è una cattiva idea, quindi in py2 dovrete ingannarlo dicendo import sys; reload(sys); sys.setdefaultencoding('utf-8'); vi presento una soluzione migliore per py3k qui sotto). quando si guarda l'output di queste tre linee:

b'EX\xc3\xa1MPLE' 
EXáMPLE 
EXÁMPLE 

si può vedere che quando upper() preso applicato al primo testo, ha agito in byte, non su caratteri. python consente il metodo upper() su byte, ma è definito solo sull'interpretazione dei byte US-ASCII. poiché utf-8 utilizza i valori all'interno di 8 bit ma all'esterno di di US-ASCII (da 128 a 255, che non vengono utilizzati da US-ASCII), quelli non saranno interessati da upper(), quindi quando si decodifica nuovamente in la seconda riga, otteniamo quella minuscola á. infine, la terza riga fa bene, e sì, sorpresa, python sembra essere consapevole del fatto che Á è la lettera maiuscola corrispondente a á. ho eseguito un test rapido per vedere quali caratteri Python 3 non consente di convertire tra lettere maiuscole e minuscole:

for cid in range(3000): 
    my_chr = chr(cid) 
    if my_chr == my_chr.upper() and my_chr == my_chr.lower(): 
    say(my_chr) 

sfogliando l'elenco rivela pochissimi episodi di lettere latine, cirillici o greci; la maggior parte dell'output sono caratteri e punteggiatura non europei. gli unici caratteri che ho trovato che Python ha sbagliato sono Ԥ/ԥ (\ u0524, \ u0525, 'cirillico {capitale | piccola} lettera pe con discensore'), quindi finché rimani fuori dai blocchi Latin Extended-X (controlla quelli, potrebbero dare sorprese), potresti effettivamente usare quel metodo. ovviamente, non ho controllato la correttezza delle mappature.

Infine, ecco cosa ho inserito nella mia sezione di avvio dell'applicazione py3k: un metodo che ridefinisce la codifica sys.stdout vede, con riferimenti numerici ai caratteri (NCR) come fallback; questo ha l'effetto che la stampa sullo standard output non solleverà mai un errore di codifica unicode. quando lavoro su Ubuntu, _sys.stdout.encoding è utf-8; quando lo stesso programma funziona su Windows, potrebbe essere qualcosa di strano come cp850. l'output potrebbe sembrare di tipo starnge, ma l'applicazione viene eseguita senza generare un'eccezione su quei terminali scuri.

#=========================================================================================================== 
# MAKE STDOUT BEHAVE IN A FAILSAFE MANNER 
#----------------------------------------------------------------------------------------------------------- 
def _harden_stdout(): 
    """Ensure that unprintable output to STDOUT does not cause encoding errors; use XML character references 
    so any kind of output gets a chance to render in a decipherable way.""" 
    global _sys_TRM 
    _sys.stdout  = _sys_TRM = _sys_io.TextIOWrapper(
    _sys.stdout.buffer, 
    encoding  = _sys.stdout.encoding, 
    errors   = 'xmlcharrefreplace', 
    line_buffering = true) 
#........................................................................................................... 
_harden_stdout() 

più un consiglio: durante il test, cerca sempre di print repr(x) o una cosa simile che rivela l'identità di x. tutti i tipi di incomprensioni possono emergere se solo print x in py2 e x è una stringa di ottetto o un oggetto unicode. è molto sconcertante e incline a causare grossi grattacapi. come ho detto, prova a muoverti almeno su py26 con quello da incantesimo letterale di importazione unicode futuro.

e di chiudere, citando una citazione: "Glifo Lefkowitz afferma che la cosa migliore nel suo articolo Encoding:

I believe that in the context of this discussion, the term "string" is meaningless. There is text, and there is byte-oriented data (which may very well represent text, but is not yet converted to it). In Python types, Text is unicode. Data is str. The idea of "non-Unicode text" is just a programming error waiting to happen."

aggiornamento: appena trovato Python 3 converte correttamente s latino: lettera S LONG al S quando il maiuscolo ordinata. !