with tutorial the para latest framework español desde cero applications python unicode bytestring

tutorial - Python y Unicode: cómo todo debería ser Unicode



the django project (6)

Perdona si esta es una pregunta larga:

Llevo unos seis meses programando en Python. Autodidacta, comenzando con el tutorial de Python y luego SO y luego usando Google para las cosas

Aquí está la parte triste: nadie me dijo que todas las cadenas deberían ser Unicode. No, no estoy mintiendo ni inventando esto, pero ¿dónde lo menciona el tutorial? Y la mayoría de los ejemplos también veo que solo hacen uso de byte strings de byte strings , en lugar de Unicode strings. de Unicode strings. Solo estaba navegando y encontré esta pregunta en SO , que dice cómo cada cadena en Python debería ser una cadena Unicode. Esto casi me hizo llorar!

Leí que cada cadena en Python 3.0 es Unicode por defecto, así que mis preguntas son para 2.x:

  1. ¿Debo hacer un

    print u''Some text'' o simplemente print ''Text'' ?

  2. Todo debería ser Unicode, significa esto, como decir que tengo una tuple :

    t = (''First'', ''Second''), it should be t = (u''First'', u''Second'')?

    Leí que puedo hacer un from __future__ import unicode_literals y luego cada cadena será una cadena Unicode, pero ¿debo hacer esto dentro de un contenedor también?

  3. Al leer / escribir en un archivo, debería usar el módulo de codecs . ¿Derecha? ¿O debería simplemente usar la forma estándar de leer / escribir y encode o decode donde sea necesario?

  4. Si obtengo la cadena desde say raw_input() , ¿también debería convertirla a Unicode?

¿Cuál es el enfoque común para manejar todos los problemas anteriores en 2.x? La from __future__ import unicode_literals ?

Lo siento por ser un noob, pero esto cambia lo que he estado haciendo durante mucho tiempo y estoy tan confundido.


1/2) Personalmente nunca he oído hablar de "usar siempre unicode". Eso me parece bastante estúpido. Supongo que entiendo si tiene previsto admitir otros idiomas que necesitan compatibilidad con Unicode. Pero aparte de eso, no haría eso, parece más doloroso de lo que vale.

3) Simplemente leería / escribiría de forma estándar y codificaría cuando fuera necesario.


El hecho de que estuvo escribiendo el código de Python durante 6 meses antes de encontrar algo sobre Unicode significa que el valor predeterminado ASCII para cadenas de Python 2.x no le causó ningún problema. Ciertamente, para un principiante tratar de comprender la idea de Unicode / code points / encoding en sí mismo es un tema difícil de abordar; por lo tanto, la mayoría de los tutoriales lo evitan de forma natural hasta que obtiene una mayor base en los fundamentos. Es por eso que en un libro como Dive Into Python, Unicode solo se menciona en capítulos posteriores .

Si necesita admitir Unicode en su aplicación, le sugiero que consulte la charla PyCon 2008 de Kumar McMillan sobre Unicode para obtener una lista de las mejores prácticas. Debe responder a sus preguntas restantes.


IMHO (mis reglas simples):

  1. ¿Debo hacer una: print u''Some text'' or just print ''Text'' ?

  2. Todo debería ser Unicode, ¿significa esto, como decir que tengo una tupla: t = (''First'', ''Second''), it should be t = (u''First'', u''Second'') ?

Bueno, uso literales de Unicode solo cuando tengo algunos caracteres por encima de ASCII 128:

print ''New York'', u''São Paulo'' t = (''New York'', u''São Paulo'')

  1. Al leer / escribir en un archivo, debería usar el módulo de códecs. ¿Derecha? ¿O debería simplemente usar la forma estándar de leer / escribir y codificar o decodificar donde sea necesario?

Si esperas texto Unicode, usa codecs.

  1. Si obtengo la cadena desde say raw_input (), ¿también debería convertirla a Unicode?

Solo si espera que el texto Unicode se transfiera a otro sistema con una codificación predeterminada distinta (incluidas las bases de datos).

EDITADO (sobre la mezcla de unicode y cadenas de bytes):

>>> print ''New York'', ''to'', u''São Paulo'' New York to São Paulo >>> print ''New York'' + '' to '' + u''São Paulo'' New York to São Paulo >>> print "Côte d''Azur" + '' to '' + u''São Paulo'' Traceback (most recent call last): File "<interactive input>", line 1, in <module> UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xc3 in position 1: ordinal not in range(128) >>> print "Côte d''Azur".decode(''utf-8'') + '' to '' + u''São Paulo'' Côte d''Azur to São Paulo

Por lo tanto, si combina una cadena de bytes que contiene utf-8 (u otro tipo de caracteres que no sea ascii) con texto Unicode sin conversión explícita, tendrá problemas, porque el valor predeterminado es ascii. El otro camino alrededor parece ser seguro. Si sigue la regla de escribir todas las cadenas que contienen non-ascii como un literal de Unicode, debería estar bien.

DESCARGO DE RESPONSABILIDAD: Vivo en Brasil, donde la gente habla portugués, un idioma con muchos caracteres que no son ascii. Mi codificación predeterminada siempre se establece en ''utf-8''. Su kilometraje puede variar en inglés / ascii systems.


La sugerencia de "usar siempre Unicode" es principalmente para facilitar la transición a Python 3. Si tiene un montón de acceso a cadenas no Unicode en su código, tomará más trabajo para portarlo.

Además, no debería tener que decidir caso por caso si una cadena debe almacenarse como Unicode o no. No deberías tener que cambiar los tipos de tus cadenas y su misma sintaxis solo porque tú también cambiaste sus contenidos.

También es fácil usar el tipo de cadena incorrecto, lo que lleva a un código que funciona en su mayoría , o un código que funciona en Linux pero no en Windows, o en una configuración regional pero no en otra. Por ejemplo, for c in "漢字" en una configuración regional UTF-8 se iterará sobre cada byte UTF-8 (los seis), no sobre cada carácter; Si eso rompe las cosas depende de lo que hagas con ellas.

En principio, nada debería romperse si usa cadenas Unicode, pero las cosas pueden romperse si usa cadenas normales cuando no debería.

Sin embargo, en la práctica, es un dolor utilizar cadenas de Unicode en todas partes en Python 2. codecs.open no elige la ubicación correcta de forma automática; esto falla:

codecs.open("blar.txt", "w").write(u"漢字")

La verdadera respuesta es:

import locale, codecs lang, encoding = locale.getdefaultlocale() codecs.open("blar.txt", "w", encoding).write(u"漢字")

... que es engorroso, obligando a las personas a realizar funciones de ayuda solo para abrir archivos. codecs.open debería usar la codificación de la locale automáticamente cuando no se especifica una; La falla de Python para hacer que una operación tan simple sea conveniente es una de las razones por las que las personas generalmente no usan Unicode en todas partes.

Finalmente, tenga en cuenta que las cadenas Unicode son aún más críticas en Windows en algunos casos. Por ejemplo, si estás en una configuración regional occidental y tienes un archivo llamado "漢字", debes usar una cadena Unicode para acceder a él, por ejemplo. os.stat(u"漢字") . Es imposible acceder a él con una cadena que no sea Unicode; simplemente no verá el archivo.

Así que, en principio, diría que la recomendación de la cadena Unicode es razonable, pero con la advertencia de que generalmente ni siquiera la sigo.


No, no todas las cadenas "deberían ser Unicode". Dentro de su código Python, usted sabe si los literales de cadena deben ser Unicode o no, por lo que no tiene ningún sentido convertir cada literal de cadena en un literal de Unicode.

Pero hay casos en los que deberías usar Unicode. Por ejemplo, si tiene una entrada arbitraria que es texto, use Unicode para ello. Más tarde o más temprano encontrará un no-americano usándolo, y él querrá que el texto se üsed tö. Y tendrá problemas en ese caso a menos que su entrada y salida utilicen la misma codificación, de lo que no puede estar seguro.

Así que en resumen, no, las cadenas no deberían ser Unicode. El texto debe ser. Pero YMMV.

Específicamente:

  1. No hay necesidad de usar Unicode aquí. Usted sabe si esa cadena es ASCII o no.

  2. Depende si necesitas combinar esas cadenas con Unicode o no.

  3. Ambos modos funcionan. Pero no codifique decodificar "cuando sea necesario". Decodificar lo antes posible, codificar lo más tarde posible. El uso de codecs funciona bien (o io, de Python 2.7).

  4. Sí.


Solo estoy agregando mi opinión personal aquí. No es tan largo y elaborado en las otras respuestas, pero tal vez pueda ayudar, también.

print u''Some text'' o simplemente print ''Text'' ?

De hecho preferiría el primero. Si sabes que solo tienes cadenas Unicode, tienes una invariante más. Varios otros idiomas (C, C ++, Perl, PHP, Ruby, Lua, ...) a veces encuentran problemas dolorosos debido a su falta de separación entre las secuencias de unidades de código y las secuencias de enteros. Encuentro el enfoque de distinción estricta entre ellos que existe en .NET, Java, Python, etc. bastante más limpio.

Todo debería ser Unicode, significa esto, como decir que tengo una tupla:

t = (''First'', ''Second'') , debería ser t = (u''First'', u''Second'')?

Sí.

Leí que puedo hacer un from __future__ import unicode_literals y luego cada cadena será una cadena Unicode, pero ¿debo hacer esto dentro de un contenedor también?

Sí. Las declaraciones futuras se aplican solo al archivo donde se usan, por lo que puede usarlas sin interferir con otros módulos. Generalmente importo todos los futuros en los módulos Python 2.x para facilitar la transición a 3.x.

Al leer / escribir en un archivo, debería usar el módulo de codecs . ¿Derecha? ¿O debería simplemente usar la forma estándar de leer / escribir y codificar o decodificar donde sea necesario?

Debe usar el módulo de codecs porque eso hace que sea imposible (o al menos muy difícil) escribir accidentalmente representaciones codificadas de manera diferente en un solo archivo. También es la forma en que funciona Python 3.x cuando abres un archivo en modo texto.

Si obtengo la cadena desde say raw_input() , ¿también debería convertirla a Unicode?

También diría que sí a esto: en la mayoría de los casos, es más fácil lidiar con una sola codificación, por lo que recomiendo convertir a cadenas de Python Unicode lo antes posible.

¿Cuál es el enfoque común para manejar todos los problemas anteriores en 2.x? La from __future__ import unicode_literals ?

No sé cuál es el enfoque común, pero uso esa declaración todo el tiempo. Solo he encontrado muy pocos problemas con este enfoque, y la mayoría de ellos están relacionados con errores en bibliotecas externas, es decir, NumPy a veces requiere cadenas de bytes sin documentar eso.