thoslin
Estoy realmente confundido. Intenté codificar pero el error decía can't decode...
.
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
Sé cómo evitar el error con el prefijo “u” en la cadena. Me pregunto por qué el error es “no se puede decodificar” cuando se llamó a codificar. ¿Qué está haciendo Python debajo del capó?
"你好".encode('utf-8')
encode
convierte un objeto Unicode en un string
objeto. Pero aquí lo has invocado en un string
objeto (porque no tienes la u). Así que Python tiene que convertir el string
a un unicode
objeto primero. Entonces hace el equivalente de
"你好".decode().encode('utf-8')
Pero la decodificación falla porque la cadena no es ASCII válida. Es por eso que recibe una queja sobre no poder decodificar.
-
¿Entonces, cuál es la solución? Especialmente si no tengo un literal de cadena, solo tengo un objeto de cadena.
– Jon Tirsen
12 de marzo de 2013 a las 7:57
-
@JonTirsen, no debe codificar un objeto de cadena. Un objeto de cadena ya está codificado. Si necesita cambiar la codificación, debe decodificarla en una cadena Unicode y luego codificarla como la codificación deseada.
–Winston Ewert
12 de marzo de 2013 a las 16:24
-
Entonces, para decirlo claramente desde arriba, puedes
"你好".decode('utf-8').encode('utf-8')
– deinonychusaurio
25 de julio de 2013 a las 8:18
-
@WinstonEwert Supongo que estaba confundido. El negocio de la codificación tiende a dejarme eternamente confundido. Supongo que mi confusión provino de mi propio problema de no saber si la entrada es una cadena o una cadena Unicode y qué codificación puede tener.
– deinonychusaurio
31 de julio de 2013 a las 17:36
-
@deinonychusaur, sí… lo entiendo.
–Winston Ewert
31 de julio de 2013 a las 18:19
ingenio
Siempre codificar de unicode a bytes.
En esta dirección, puedes elegir la codificación.
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好
La otra forma es decodificar de bytes a Unicode.
En esta dirección, tienes que saber cuál es la codificación.
>>> bytes="\xe4\xbd\xa0\xe5\xa5\xbd"
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好
Este punto no se puede enfatizar lo suficiente. Si quiere evitar jugar unicode “whack-a-mole”, es importante comprender lo que sucede a nivel de datos. Aquí se explica de otra manera:
- Un objeto Unicode ya está decodificado, nunca querrás llamar
decode
en eso. - Un objeto de cadena de bytes ya está codificado, nunca querrá llamar
encode
en eso.
Ahora, al ver .encode
en una cadena de bytes, Python 2 primero intenta convertirlo implícitamente en texto (un unicode
objeto). Del mismo modo, al ver .decode
en una cadena Unicode, Python 2 implícitamente intenta convertirla en bytes (un str
objeto).
Estas conversiones implícitas son la razón por la que puede obtener Unicode
Decode
Error
cuando has llamado encode
. Es porque la codificación generalmente acepta un parámetro de tipo unicode
; al recibir un str
parámetro, hay una decodificación implícita en un objeto de tipo unicode
antes de volver a codificarlo con otra codificación. Esta conversión elige un decodificador ‘ascii’ predeterminado†dándote el error de decodificación dentro de un codificador.
De hecho, en Python 3 los métodos str.decode
y bytes.encode
ni siquiera existen. Su remoción fue un [controversial] tratar de evitar esta confusión común.
† … o cualquier codificación sys.getdefaultencoding()
menciones; por lo general esto es ‘ascii’
-
Entonces, ¿quiere decir que Python decodifica la cadena de bytes antes de codificar?
– Thoslin
10 de marzo de 2012 a las 5:28
-
@thoslin exactamente, agregué más detalles.
– Wim
02/06/2014 a las 18:00
-
¿Qué es _ y por qué faltan paréntesis en sus declaraciones impresas?
– Sin errores
30 de septiembre de 2017 a las 3:24
-
@NoBugs 1. en el REPL,
_
se refiere al valor anterior 2. porque esta es una pregunta de python-2.x.– Wim
30 de septiembre de 2017 a las 3:37
-
Gracias por la pista. Para mi caso, la solución correcta fue simplemente .decode(‘utf-8’). Ejecuté Subprocess.popen(…).communicate() que devolvió bytes que contenían caracteres alemanes ä, ö, ü y el .decode() normal (sin el parámetro ‘utf-8’) falló. Con el parámetro ‘utf-8’ funciona.
– Alexander Samoylov
20 mayo 2022 a las 13:25
Dadaso Zanzane
Puedes probar esto
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
O
También puedes intentar seguir
Agregue la siguiente línea en la parte superior de su archivo .py.
# -*- coding: utf-8 -*-
-
¡Esta debe ser una respuesta aceptada!
– Alexei
29 de abril de 2022 a las 9:29
johnsyweb
Si está utilizando Python literal de cadena es Unicode prefijándolo con un u
:
Python 2.7.2 (default, Jan 14 2012, 23:14:09)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
Otras lecturas: CÓMO Unicode.
Qingtian
Tu usas u"你好".encode('utf8')
para codificar una cadena Unicode. Pero si quieres representar "你好"
, deberías decodificarlo. Al igual que:
"你好".decode("utf8")
Obtendrás lo que quieres. Tal vez debería aprender más sobre codificar y decodificar.
kenorb
En caso de que esté tratando con Unicode, a veces en lugar de encode('utf-8')
también puede intentar ignorar los caracteres especiales, por ejemplo
"你好".encode('ascii','ignore')
o como something.decode('unicode_escape').encode('ascii','ignore')
como se sugiere aquí.
No es particularmente útil en este ejemplo, pero puede funcionar mejor en otros escenarios cuando no es posible convertir algunos caracteres especiales.
Alternativamente, puede considerar reemplazar un carácter particular usando replace()
.
0rango
Si está iniciando el intérprete de python desde un shell en Linux o sistemas similares (BSD, no estoy seguro acerca de Mac), también debe verificar la codificación predeterminada para el shell.
Llamada locale charmap
desde el shell (no el intérprete de python) y debería ver
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $
Si este no es el caso, y ve algo más, por ejemplo
[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $
Python (al menos en algunos casos, como en el mío) heredará la codificación del shell y no podrá imprimir (¿algunos? ¿Todos?) caracteres Unicode. La propia codificación predeterminada de Python que ve y controla a través de sys.getdefaultencoding()
y sys.setdefaultencoding()
en este caso se ignora.
Si descubre que tiene este problema, puede solucionarlo
[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $
(O, alternativamente, elija el mapa de teclas que desee en lugar de en_EN). También puede editar /etc/locale.conf
(o cualquier archivo que gobierne la definición de configuración regional en su sistema) para corregir esto.
Tenga en cuenta que este problema se solucionó en 3.x: las cadenas son simplemente Unicode y
bytes
los objetos son simplemente bytes en bruto, y nunca los dos se encontrarán. Las cadenas no realizan ninguna decodificación implícita cuando.encode
se llama; De hecho,.encode
es no soportado en absoluto, ya que no tiene sentido. El extraño comportamiento solo estaba presente en 2.x como un truco de compatibilidad en primer lugar, debido a la forma en que se introdujo Unicode en el lenguaje.– Karl Knechtel
4 de enero a las 6:46