Cadenas y codificaciones de caracteres en Python

Hola, aquí está el blog de Token_w, bienvenido. El
artículo de hoy explica la codificación de cadenas y caracteres en Python. Incluye conocimientos teóricos básicos y aplicaciones prácticas. Espero que les sea útil.
Si les es útil, espero obtener sus gustos y favoritos. agradecido

I. Introducción

La codificación de caracteres en Python es un tema anticuado y los colegas han escrito muchos artículos al respecto. Algunas personas se hacen eco de lo que otros dicen, y algunos escriben profundamente. Recientemente, vi que este tema se discutía nuevamente en un video didáctico de una reconocida institución de capacitación, y la explicación aún no era satisfactoria, por lo que quise escribir este texto. Por un lado, ordenar el conocimiento relevante, por otro lado, espero ayudar a otros.

La codificación predeterminada de Python2 es ASCII, que no puede reconocer caracteres chinos y debe especificarse explícitamente; la codificación predeterminada de Python3 es Unicode, que puede reconocer caracteres chinos.

Creo que ha visto la explicación de "procesamiento chino en Python" similar a la anterior en muchos artículos, y creo que realmente lo entendió cuando vio por primera vez tal explicación. Pero después de mucho tiempo, si encuentra problemas relacionados repetidamente, sentirá que su comprensión no es tan clara. Si entendemos el papel de la codificación predeterminada mencionada anteriormente, entenderemos el significado de esa oración con mayor claridad.

2. Conceptos relacionados

2.1 Caracteres y bytes

Un carácter no es equivalente a un byte. Los caracteres son símbolos que los humanos pueden reconocer, y estos símbolos deben estar representados por bytes que las computadoras puedan reconocer para guardarlos en el almacenamiento informático. A menudo, existen múltiples métodos de representación para un carácter, y diferentes métodos de representación utilizan diferentes números de bytes. Los diferentes métodos de representación mencionados aquí se refieren a la codificación de caracteres, por ejemplo, las letras AZ pueden representarse por código ASCII (ocupa un byte), también pueden representarse por UNICODE (ocupa dos bytes) y también pueden representarse por UTF-8 (ocupa un byte). El papel de la codificación de caracteres es convertir caracteres reconocibles por humanos en códigos de bytes reconocibles por máquinas, y viceversa.

UNICDOE es la cadena de caracteres real y los códigos de caracteres como ASCII, UTF-8 y GBK representan cadenas de bytes . Con respecto a este punto, a menudo podemos ver tales descripciones en los documentos oficiales de Python "Cadena Unicode", "traducir una cadena Unicode en una secuencia de bytes"

Escribimos código en archivos y los caracteres se almacenan en archivos en bytes, por lo que cuando definimos una cadena en un archivo, es comprensible que se trate como una cadena de bytes. Sin embargo, lo que necesitamos es una cadena, no una cadena de bytes. Un excelente lenguaje de programación debe distinguir estrictamente la relación entre los dos y brindar un soporte ingenioso y perfecto. El lenguaje JAVA es tan bueno que nunca consideré estos problemas que los programadores no deberían manejar antes de aprender sobre Python y PHP. Desafortunadamente, muchos lenguajes de programación intentan confundir "cadena" y "cadena de bytes", y usan cadenas de bytes como cadenas. PHP y Python2 pertenecen a este lenguaje de programación. La operación que mejor ilustra este problema es tomar la longitud de una cadena que contiene caracteres chinos:

  • Tome la longitud de la cadena, el resultado debe ser el número de todas las cadenas, sin importar chino o inglés
  • La longitud de la cadena de bytes correspondiente a la cadena está relacionada con la codificación de caracteres utilizada en el proceso de codificación (codificación) (por ejemplo: codificación UTF-8, un carácter chino debe estar representado por 3 bytes; codificación GBK, un carácter chino Necesita 2 bytes para representar)
    Nota: La codificación de caracteres predeterminada del terminal cmd de Windows es GBK, por lo que los caracteres chinos ingresados ​​​​en cmd deben estar representados por dos bytes
# Python2
a = 'Hello,中国'  # 字节串,长度为字节个数 = len('Hello,')+len('中国') = 6+2*2 = 10
b = u'Hello,中国'  # 字符串,长度为字符个数 = len('Hello,')+len('中国') = 6+2 = 8
c = unicode(a, 'gbk')  # 其实b的定义方式是c定义方式的简写,都是将一个GBK编码的字节串解码(decode)为一个Uniocde字符串

print(type(a), len(a))
# (<type 'str'>, 10)
print(type(b), len(b))
# (<type 'unicode'>, 8)
print(type(c), len(c))
# (<type 'unicode'>, 8)

El soporte para cadenas en Python 3 ha cambiado mucho y los detalles se presentarán a continuación.

2.2 Codificación y decodificación

Primero haga un poco de ciencia popular: la codificación de caracteres UNICODE también es un mapeo entre caracteres y números, pero los números aquí se llaman puntos de código, que en realidad son números hexadecimales.

La documentación oficial de Python describe la relación entre cadenas Unicode, cadenas de bytes y codificaciones:

Una cadena Unicode es una secuencia de puntos de código (punto de código), y el punto de código varía de 0 a 0x10FFFF (correspondiente a 1114111 en decimal). Esta secuencia de puntos de código debe representarse como un conjunto de bytes (valores entre 0 y 255) en el almacenamiento (incluida la memoria y el disco físico), y las reglas para convertir cadenas Unicode en secuencias de bytes se denominan codificaciones.

La codificación mencionada aquí no se refiere a la codificación de caracteres, sino al proceso de codificación y las reglas de asignación entre puntos de código y bytes de caracteres Unicode utilizados en este proceso . Esta asignación no tiene que ser una simple asignación uno a uno, por lo que el proceso de codificación no tiene que manejar todos los caracteres Unicode posibles, por ejemplo:

Las reglas para convertir una cadena Unicode a una codificación ASCII son simples, para cada punto de código:

  • Si el valor del punto de código < 128, cada byte tiene el mismo valor que el punto de código

  • Si el valor del punto de código es >= 128, la cadena Unicode no se puede representar en esta codificación (en este caso, Python generará una excepción UnicodeEncodeError). La conversión de una cadena Unicode
    a la codificación UTF-8 utiliza las siguientes reglas:

  • Si el valor del punto de código es < 128, se representa mediante el valor de byte correspondiente (igual que Unicode a byte ASCII)

  • Si el valor del punto de código es >= 128, se convierte en una secuencia de 2 bytes, 3 bytes o 4 bytes, cada byte de la secuencia está entre 128 y 255.
    Breve resumen:

  • Codificación (codificar) : el proceso y las reglas para convertir una cadena Unicode (punto de código de entrada) en una cadena de bytes correspondiente a una codificación de caracteres específica

  • Decodificación (decodificación) : el proceso y las reglas para convertir una cadena de bytes de una codificación de caracteres específica en una cadena Unicode correspondiente (punto de código en ella) Se puede
    ver que, ya sea que se esté codificando o decodificando, se requiere un factor importante, que es una codificación de caracteres específica . Debido a que un carácter está codificado con diferentes codificaciones de caracteres, el valor del byte y la cantidad de bytes son diferentes en la mayoría de los casos, y viceversa.

3. La codificación predeterminada en Python

3.1 Proceso de ejecución del archivo de código fuente de Python

Todos sabemos que los archivos en el disco se almacenan en formato binario y los archivos de texto se almacenan en bytes de una codificación específica. El editor especifica la codificación de caracteres del archivo de código fuente del programa. Por ejemplo, cuando usamos Pycharm para escribir un programa Python, especificaremos la codificación del proyecto y la codificación del archivo como UTF-8, luego el código Python se convertirá a UTF cuando se guarda en el disco.-8 codifica los bytes correspondientes (proceso de codificación) y los escribe en el disco. Al ejecutar el código en el archivo de código de Python, después de que el intérprete de Python lea la cadena de bytes en el archivo de código de Python, debe convertirla en una cadena UNICODE (proceso de decodificación) antes de realizar operaciones posteriores.

Como se explicó anteriormente, este proceso de conversión (decodificación, decodificación) requiere que especifiquemos la codificación de caracteres utilizada por los bytes guardados en el archivo, para que podamos saber que estos bytes pueden encontrar sus puntos de código correspondientes en el código universal UNICODE y Unicode qué Lo es. Todo el mundo está familiarizado con la forma de especificar la codificación de caracteres aquí, de la siguiente manera:

# -*- coding:utf-8 -*-

inserte la descripción de la imagen aquí

3.2 Codificación por defecto

Entonces, si no especificamos la codificación de caracteres al comienzo del archivo de código, ¿qué codificación de caracteres usará el intérprete de Python para convertir los bytes leídos del archivo de código en puntos de código UNICODE? Al igual que cuando configuramos algún software, hay muchas opciones predeterminadas. Necesitamos establecer la codificación de caracteres predeterminada dentro del intérprete de Python para resolver este problema. Esta es la "codificación predeterminada" mencionada al principio del artículo. Por lo tanto, el problema de los caracteres chinos de Python que todos dijeron se puede resumir en una oración: cuando el byte no se puede convertir a través de la codificación de caracteres predeterminada, se producirá un error de decodificación (UnicodeEncodeError).

La codificación predeterminada utilizada por los intérpretes de Python 2 y Python 3 es diferente. Podemos obtener la codificación predeterminada a través de sys.getdefaultencoding():

# Python2
import sys
print(sys.getdefaultencoding() )
# 'ascii'

# Python3
import sys
print(sys.getdefaultencoding() )
# 'utf-8'

Por lo tanto, para Python2, cuando el intérprete de Python lee el código de bytes de los caracteres chinos e intenta decodificar la operación, primero verificará si el encabezado del archivo de código actual indica si la codificación de caracteres correspondiente al código de bytes almacenado en el archivo de código actual es Qué. Si no se especifica, se usará la codificación de caracteres predeterminada "ASCII" para la decodificación, lo que provocará una falla en la decodificación y generará el siguiente error:

SyntaxError: Non-ASCII character '\xc4' in file xxx.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Para Python3, el proceso de ejecución es el mismo, pero el intérprete de Python3 usa "UTF-8" como codificación predeterminada, pero esto no significa que sea totalmente compatible con los problemas chinos. Por ejemplo, cuando desarrollamos en Windows, el proyecto de Python y los archivos de código utilizan la codificación GBK predeterminada, lo que significa que los archivos de código de Python se convierten en bytecodes en formato GBK y se guardan en el disco. Cuando el intérprete de Python3 ejecuta el archivo de código, cuando intenta usar UTF-8 para decodificar, la decodificación también falla, lo que genera el siguiente error:

SyntaxError: Non-UTF-8 code starting with '\xc4' in file xxx.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

3.3 Mejores prácticas

  • Después de crear un proyecto, primero confirme si la codificación de caracteres del proyecto se ha establecido en UTF-8
  • Para ser compatible con Python2 y Python3, declare la codificación de caracteres en el encabezado del código: - - codificación:utf-8 - -

4. Soporte para cadenas en Python2 y Python3

De hecho, la mejora del soporte de cadenas en Python3 no es solo para cambiar la codificación predeterminada, sino para volver a implementar la cadena, y se ha dado cuenta del soporte integrado para UNICODE.Desde este punto de vista, Python es tan bueno como JAVA. . Echemos un vistazo a la diferencia entre el soporte para cadenas en Python2 y Python3:

(1) Python2

Las siguientes tres clases proporcionan soporte para cadenas en Python2

class basestring(object)
    class str(basestring)
    class unicode(basestring)

Al ejecutar help(str) y help(bytes) encontrará que el resultado es la definición de la clase str, que también muestra que str en Python2 es una cadena de bytes, y el objeto Unicode posterior corresponde a la cadena real.

#!/usr/bin/env python
# -*- coding:utf-8 -*-

a = '你好'
b = u'你好'

print(type(a), len(a))
print(type(b), len(b))

Resultado de salida:

(<type 'str'>, 6)
(<type 'unicode'>, 2)

(2) Python3

El soporte para cadenas en Python3 se ha simplificado a nivel de la clase de implementación, se ha eliminado la clase Unicode y se ha agregado una clase de bytes. En la superficie, se puede considerar que str y unicode en Python3 se han combinado en uno.

class bytes(object)
class str(object)

De hecho, Python3 se dio cuenta de los errores anteriores y comenzó a distinguir claramente entre cadenas y bytes. Por lo tanto, str en Python3 ya es una cadena real y los bytes están representados por una clase de bytes separada. En otras palabras, Python3 define las cadenas de forma predeterminada, lo que brinda soporte integrado para UNICODE y reduce la carga de los programadores para el procesamiento de cadenas.

#!/usr/bin/env python
# -*- coding:utf-8 -*-

a = '你好'
b = u'你好'
c = '你好'.encode('gbk')

print(type(a), len(a))
print(type(b), len(b))
print(type(c), len(c))

Resultado de salida:

<class 'str'> 2
<class 'str'> 2
<class 'bytes'> 4

5. Conversión de codificación de caracteres

Como se mencionó anteriormente, las cadenas UNICODE se pueden convertir en bytes de cualquier codificación de caracteres, como se muestra en la figura:
inserte la descripción de la imagen aquí
Entonces es fácil para todos pensar en una pregunta, es decir, se pueden convertir bytes de diferentes codificaciones de caracteres entre sí a través de Unicode ? La respuesta es sí.

El proceso de conversión de codificación de caracteres de cadenas en Python2 es:
cadena de bytes –> decodificación ('codificación de caracteres original') –> cadena Unicode –> codificación ('nueva codificación de caracteres') –> cadena de bytes

#!/usr/bin/env python
# -*- coding:utf-8 -*-


utf_8_a = '我爱中国'
gbk_a = utf_8_a.decode('utf-8').encode('gbk')
print(gbk_a.decode('gbk'))

Resultado de salida:

我爱中国

La cadena definida en Python3 es Unicode de forma predeterminada, por lo que no es necesario decodificarla primero y puede codificarse directamente en una nueva codificación de caracteres:
cadena –> codificar('nueva codificación de caracteres') –> cadena de bytes

#!/usr/bin/env python
# -*- coding:utf-8 -*-


utf_8_a = '我爱中国'
gbk_a = utf_8_a.encode('gbk')
print(gbk_a.decode('gbk'))

Resultado de salida:

Amo China
Lo último que hay que explicar es que Unicode no es un diccionario de Youdao, ni es un traductor de Google, no puede traducir un chino a un inglés. El proceso de conversión de codificación de caracteres correcto solo cambia la representación de bytes del mismo carácter, pero el símbolo del carácter en sí no debería cambiar, por lo que no todas las conversiones entre codificaciones de caracteres son significativas. ¿Cómo entender esta frase? Por ejemplo, después de que la "China" codificada en GBK se convierta en codificación de caracteres UTF-8, solo se representa mediante 4 bytes en 6 bytes, pero su representación de caracteres debe seguir siendo "China" en lugar de "Hola" o "China". .

Pasé mucho espacio para introducir conceptos y teorías en el frente y centrarme en la práctica más adelante, espero que les sea útil.

Apéndice 6. Codificación de caracteres

1. Código ASCII

El código ASCII es una especificación de codificación temprana desarrollada por los Estados Unidos, que solo puede representar 128 caracteres, incluidos caracteres ingleses, números arábigos, caracteres occidentales y 32 caracteres de control. En pocas palabras, es la siguiente tabla:
inserte la descripción de la imagen aquí

2. Código ASCII extendido (ASCII extendido)

En pocas palabras, la aparición del código ASCII extendido se debe a que ASCII no es suficiente, por lo que la tabla ASCII continúa expandiéndose a 256 símbolos. Pero debido al ASCII extendido, diferentes países tienen diferentes estándares, lo que provocó el nacimiento de la codificación Unicode. La tabla de códigos ASCII extendida es la siguiente:
inserte la descripción de la imagen aquí

3. código único

Para ser precisos, Unicode no es un formato de codificación, sino un juego de caracteres. Este conjunto de caracteres contiene todos los símbolos actuales del mundo. Además, en el original, algunos caracteres podían estar representados por un byte, es decir, 8 bits, en Unicode, la longitud de todos los caracteres se unifica a 16 bits, por lo que los caracteres son de longitud fija. Unicode se ve así:

\u4f60\u597d\u4e2d\u56fd\uff01\u0068\u0065\u006c\u006c\u006f\uff0c\u0031\u0032\u0033

El Unicode anterior significa "¡Hola China! hola, 123".

Con respecto a Unicode, todos los caracteres se pueden encontrar en este sitio web: https://unicode-table.com/en/
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

4 GB2312

Cuando los chinos obtienen computadoras, necesitan codificar caracteres chinos. Sobre la base de la tabla de códigos ASCII, el significado de los caracteres inferiores a 127 es el mismo que el original, y dos bytes superiores a 127 se conectan entre sí para representar caracteres chinos. El byte anterior es 87 desde 0xA1 (161) hasta 0xF7 ( 247). Un byte se denomina byte alto, y el último byte tiene 94 bytes desde 0xA1 (161) hasta 0xFE (254), que se denomina byte bajo. Los dos se pueden combinar para formar unas 8000 combinaciones, que se utilizan para representar 6763 Caracteres chinos simplificados, símbolos matemáticos, letras romanas, caracteres japoneses, etc. Los números, la puntuación y las letras codificados son códigos de dos bytes de longitud, que se denominan caracteres de "ancho completo", y los caracteres originales por debajo de 127 en la tabla de códigos ASCII se denominan caracteres de "ancho medio". En pocas palabras, GB2312 es una extensión de caracteres chinos simplificados basada en ASCII.

Tabla de códigos GB2312: http://www.fileformat.info/info/charset/GB2312/list.htm

5. GBK

En términos simples, GBK es una extensión adicional de GB2312 (K es la consonante inicial de la palabra "expandir" en chino pinyin kuo zhan (extensión), que contiene 21886 caracteres y símbolos chinos, que son totalmente compatibles con GB2312.

6 GB18030

GB18030 contiene 70244 caracteres y caracteres chinos, que es más completo y compatible con GB 2312-1980 y GBK. GB18030 admite caracteres chinos de minorías étnicas y también incluye caracteres chinos tradicionales y caracteres chinos japoneses y coreanos. Su codificación es una codificación de longitud variable simple, doble y de cuatro bytes.

7. UTF (formato de transferencia UCS)

UTF es la implementación de Unicode más utilizada en Internet. El más utilizado es UTF-8, lo que significa que los datos se transmiten 8 bits a la vez, además existe UTF-16.

UTF-8 se ve así, "¡Hola, China! Hola, 123":

¡Hola chino! hola, 123

8. Breve resumen

  • El pueblo chino ha ampliado y transformado el código ASCII chino para producir el código GB2312, que puede representar más de 6000 caracteres chinos de uso común.
  • Hay demasiados caracteres chinos, incluidos los caracteres tradicionales y varios caracteres, por lo que se produjo la codificación GBK, que incluía la codificación en GB2312 y se expandió mucho al mismo tiempo.
  • China es un país multiétnico, cada nación tiene su propio sistema de idioma independiente, para representar esos caracteres, continúe expandiendo el código GBK al código GB18030.
  • Cada país, como China, codifica su propio idioma, por lo que aparecen varios códigos. Si no instala el código correspondiente, no puede explicar lo que quiere expresar el código correspondiente.
  • Finalmente, una organización llamada ISO no pudo soportarlo más. Juntos, crearon un código llamado UNICODE, que es tan grande que puede acomodar cualquier carácter y logotipo del mundo. Entonces, siempre que la computadora tenga un sistema de codificación UNICODE, no importa qué tipo de texto haya en el mundo, solo necesita guardar el archivo en codificación UNICODE y otras computadoras pueden interpretarlo normalmente.
  • En la transmisión de red de UNICODE aparecieron dos estándares UTF-8 y UTF-16, cada transmisión de 8 bits y 16 bits respectivamente. Entonces, algunas personas tendrán preguntas, dado que UTF-8 puede guardar tantos caracteres y símbolos, ¿por qué hay tanta gente que usa GBK y otras codificaciones en China? Debido a que UTF-8 y otras codificaciones tienen un tamaño relativamente grande y ocupan mucho espacio en la computadora, si la mayoría de los usuarios son chinos, también se pueden usar GBK y otras codificaciones.

Supongo que te gusta

Origin blog.csdn.net/weixin_61587867/article/details/132296654
Recomendado
Clasificación