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. !
py3k fa correttamente – SilentGhost