Python Language
Unicode y bytes
Buscar..
Sintaxis
- str.encode (codificación, errores = 'estricto')
- bytes.decode (codificación, errores = 'estricto')
- abierto (nombre de archivo, modo, codificación = Ninguno)
Parámetros
Parámetro | Detalles |
---|---|
codificación | La codificación a utilizar, por ejemplo, 'ascii' , 'utf8' , etc ... |
errores | El modo de errores, por ejemplo, 'replace' para reemplazar los caracteres incorrectos con signos de interrogación, 'ignore' para ignorar los caracteres incorrectos, etc. |
Lo esencial
En Python 3, str
es el tipo para cadenas habilitadas para Unicode, mientras que bytes
es el tipo para secuencias de bytes sin procesar.
type("f") == type(u"f") # True, <class 'str'>
type(b"f") # <class 'bytes'>
En Python 2, una cadena casual era una secuencia de bytes sin procesar por defecto y la cadena Unicode era cada cadena con el prefijo "u".
type("f") == type(b"f") # True, <type 'str'>
type(u"f") # <type 'unicode'>
Unicode a bytes
Las cadenas Unicode se pueden convertir a bytes con .encode(encoding)
.
Python 3
>>> "£13.55".encode('utf8')
b'\xc2\xa313.55'
>>> "£13.55".encode('utf16')
b'\xff\xfe\xa3\x001\x003\x00.\x005\x005\x00'
Python 2
en py2, la codificación de la consola predeterminada es sys.getdefaultencoding() == 'ascii'
y no utf-8
como en py3, por lo tanto, imprimirla como en el ejemplo anterior no es directamente posible.
>>> print type(u"£13.55".encode('utf8'))
<type 'str'>
>>> print u"£13.55".encode('utf8')
SyntaxError: Non-ASCII character '\xc2' in...
# with encoding set inside a file
# -*- coding: utf-8 -*-
>>> print u"£13.55".encode('utf8')
£13.55
Si la codificación no puede manejar la cadena, se genera un `UnicodeEncodeError`:
>>> "£13.55".encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\xa3' in position 0: ordinal not in range(128)
Bytes a Unicode
Los bytes se pueden convertir en cadenas Unicode con .decode(encoding)
.
¡Una secuencia de bytes solo se puede convertir en una cadena Unicode a través de la codificación apropiada!
>>> b'\xc2\xa313.55'.decode('utf8')
'£13.55'
Si la codificación no puede manejar la cadena, se UnicodeDecodeError
un UnicodeDecodeError
:
>>> b'\xc2\xa313.55'.decode('utf16')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/csaftoiu/csaftoiu-github/yahoo-groups-backup/.virtualenv/bin/../lib/python3.5/encodings/utf_16.py", line 16, in decode
return codecs.utf_16_decode(input, errors, True)
UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x35 in position 6: truncated data
Codificación / decodificación de manejo de errores.
.encode
y .decode
tienen modos de error.
El valor predeterminado es 'strict'
, que genera excepciones en caso de error. Otros modos son más indulgentes.
Codificación
>>> "£13.55".encode('ascii', errors='replace')
b'?13.55'
>>> "£13.55".encode('ascii', errors='ignore')
b'13.55'
>>> "£13.55".encode('ascii', errors='namereplace')
b'\\N{POUND SIGN}13.55'
>>> "£13.55".encode('ascii', errors='xmlcharrefreplace')
b'£13.55'
>>> "£13.55".encode('ascii', errors='backslashreplace')
b'\\xa313.55'
Descodificación
>>> b = "£13.55".encode('utf8')
>>> b.decode('ascii', errors='replace')
'��13.55'
>>> b.decode('ascii', errors='ignore')
'13.55'
>>> b.decode('ascii', errors='backslashreplace')
'\\xc2\\xa313.55'
Moral
De lo anterior se desprende claramente que es vital mantener sus codificaciones rectas cuando se trata de unicode y bytes.
Archivo I / O
Los archivos abiertos en un modo no binario (por ejemplo, 'r'
o 'w'
) tratan con cadenas. La codificación sordera es 'utf8'
.
open(fn, mode='r') # opens file for reading in utf8
open(fn, mode='r', encoding='utf16') # opens file for reading utf16
# ERROR: cannot write bytes when a string is expected:
open("foo.txt", "w").write(b"foo")
Los archivos abiertos en modo binario (por ejemplo, 'rb'
o 'wb'
) tratan con bytes. No se puede especificar ningún argumento de codificación ya que no hay codificación.
open(fn, mode='wb') # open file for writing bytes
# ERROR: cannot write string when bytes is expected:
open(fn, mode='wb').write("hi")