¿Cómo puedo convertir Unicode a mayúsculas para imprimirlo?

Tengo esto:

>>> print 'example' example >>> print 'exámple' exámple >>> print 'exámple'.upper() EXáMPLE 

Lo que necesito hacer para imprimir:

 EXÁMPLE 

(Donde la ‘a’ obtiene su acento acudo, pero en mayúsculas).

Estoy usando Python 2.6.

Creo que es tan simple como no convertir a ASCII primero.

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

En Python 2.x, simplemente convierte la cadena a Unicode antes de llamar a upper (). Usando su código, que está en formato utf-8 en esta página 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 llamada a decode lleva de su formato actual a Unicode. Luego puedes convertirlo a otro formato, como utf-8, usando codificar. Si el carácter estaba en, digamos, iso-8859-2 (checo, etc., en este caso), en su lugar, usaría el s.decode('iso-8859-2').upper() .

Como en mi caso, si su terminal no es compatible con Unicode / utf-8, lo mejor que puede esperar es una representación hexadecimal de los caracteres (como la mía) o convertirla de forma perdida utilizando s.decode('utf-8').upper().encode('ascii', 'replace') , que da como resultado ‘EX? MPLE’. Si no puede hacer que su terminal se vea unicode, escriba la salida en un archivo en formato utf-8 y ábrala en su editor favorito.

En primer lugar, solo uso Python 3.1 en estos días; su mérito central es tener cadenas de bytes desambiguadas de objetos Unicode. esto hace que la gran mayoría de las manipulaciones de texto sean mucho más seguras de lo que solía ser el caso. ponderando los billones de preguntas de los usuarios con respecto a los problemas de encoding de python 2.x, la convención de u'äbc de python 2.1 fue solo un error; Con bytes explícitos y bytearray , la vida se vuelve mucho más fácil.

en segundo lugar, si py3k no es su sabor, intente ir from __future__ import unicode_literals , ya que esto imitará el comportamiento de py3k en python 2.6 y 2.7. esto hubiera evitado el error (fácilmente cometido) que hiciste al decir print 'exámple'.upper() . esencialmente, esto es lo mismo que en py3k: print( 'exámple'.encode( 'utf-8' ).upper() ) . compara estas versiones (para py3k):

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

La primera es, básicamente, lo que hiciste cuando 'exámple' una cadena 'exámple' , siempre que configures tu encoding predeterminada en utf-8 (de acuerdo con un pronunciamiento BDFL, establecer la encoding predeterminada en el tiempo de ejecución es una mala idea). py2 tendrás que engañarlo diciendo import sys; reload( sys ); sys.setdefaultencoding( 'utf-8' ) ; presento una mejor solución para py3k a continuación). Cuando miras la salida de estas tres líneas:

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

puede ver que cuando upper() se aplicó al primer texto, actuó en bytes, no en caracteres. python permite el método upper() en bytes, pero solo se define en la interpretación US-ASCII de bytes. ya que utf-8 usa valores dentro de 8 bits pero fuera de US-ASCII (128 hasta 255, que no son utilizados por US-ASCII), estos no se verán afectados por upper() , por lo que cuando decodifiquemos de nuevo en el segundo línea, obtenemos esa minúscula á . finalmente, la tercera línea lo hace bien, y sí, sorpresa, Python parece ser consciente de que Á es la letra mayúscula correspondiente a á . Ejecuté una prueba rápida para ver qué caracteres python 3 no convierte entre mayúsculas y minúsculas:

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

la lectura de la lista revela muy pocas incidencias de letras latinas, cirílicas o griegas; La mayor parte de la salida es de caracteres no europeos y de puntuación. los únicos caracteres que pude encontrar que Python se equivocaron son Ԥ / ԥ (\ u0524, \ u0525, ‘cyrillic {mayúscula | mayúscula} pe con descensor’), por lo que siempre y cuando te mantengas fuera de los bloques Latin Extended-X ( echa un vistazo a esos, podrían darte sorpresas), podrías usar ese método. por supuesto, no verifiqué la exactitud de los mapeos.

Por último, esto es lo que pongo en la sección de arranque de mi aplicación py3k: un método que redefine la encoding que ve sys.stdout , con referencias numéricas de caracteres (NCR) como respaldo; esto tiene el efecto de que la impresión en la salida estándar nunca generará un error de encoding Unicode. cuando trabajo en ubuntu, _sys.stdout.encoding es utf-8 ; cuando el mismo progtwig se ejecuta en Windows, podría ser algo extraño como cp850 . la salida puede parecer inmejorable, pero la aplicación se ejecuta sin generar una excepción en esos terminales de poca potencia.

 #=========================================================================================================== # 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() 

Un consejo más: cuando realice la prueba, siempre intente print repr( x ) o algo similar que revele la identidad de x . todo tipo de malentendidos puede surgir si solo print x en py2 x es una cadena de octetos o un objeto Unicode. es muy desconcertante y propenso a rascarse mucho la cabeza. como dije, intente pasar al menos a py26 con eso del futuro importar un encantamiento de literales Unicode.

y para cerrar, citando una cita: “Glyph Lefkowitz lo dice mejor en su artículo Codificación :

Creo que en el contexto de esta discusión, el término “cadena” no tiene sentido. Hay texto y hay datos orientados a bytes (que pueden representar texto, pero que aún no se han convertido). En los tipos de Python, el texto es unicode. Los datos son str. La idea de “texto no Unicode” es solo un error de progtwigción esperando a suceder “.

actualización: acaba de encontrar python 3 convierte correctamente ſ LETRA PEQUEÑA LETRA LARGA S a S al realizar mayúsculas. ¡ordenado!

Creo que hay algunos antecedentes que nos faltan aquí:

 >>> type('hello')  >>> type(u'hello')  

Mientras se utilicen cadenas “Unicode” en lugar de cadenas “nativas”, los operadores como upper () operarán teniendo en cuenta Unicode. FWIW, Python 3 usa unicode de forma predeterminada, lo que hace que la distinción sea en gran medida irrelevante.

Tomar una cadena de unicode a str y luego volver a unicode es subóptimo de muchas maneras, y muchas bibliotecas producirán una salida de unicode si lo desea; así que intente usar solo objetos unicode para cadenas internamente siempre que pueda.

Intentalo:

 s = 'exámple' print unicode(s).upper()