Este problema ocurre comúnmente cuando se cambia de py2 a py3. En py2 plaintext
es tanto una cadena como un tipo de matriz de bytes . En py3 plaintext
es solo una cadena , y el método outfile.write()
realmente toma una matriz de bytes cuando outfile
se abre en modo binario, por lo que se genera una excepción. Cambie la entrada a plaintext.encode('utf-8')
para solucionar el problema. Sigue leyendo si esto te molesta.
En AP2, la declaración de file.write hacía parecer como que ha pasado en una cadena: file.write(str)
. En realidad le estaban pasando en una matriz de bytes, que debería haber sido la lectura de la declaración de la siguiente manera: file.write(bytes)
. Si lo lees así, el problema es simple, file.write(bytes)
necesita un tipo de bytes y en py3 para obtener bytes de un str lo conviertes:
py3>> outfile.write(plaintext.encode('utf-8'))
¿Por qué los documentos de py2 declararon file.write
tomar una cadena? Bueno, en py2 la distinción de declaración no importaba porque:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
La clase str-bytes de py2 tiene métodos / constructores que hacen que se comporte como una clase de cadena en algunos aspectos y una clase de matriz de bytes en otros. Conveniente para file.write
no es así ?:
py2>> plaintext='my string literal'
py2>> type(plaintext)
str #is it a string or is it a byte array? it's both!
py2>> outfile.write(plaintext) #can use plaintext as a byte array
¿Por qué py3 rompió este buen sistema? Bueno, porque en py2 las funciones básicas de cadena no funcionaban para el resto del mundo. ¿Medir la longitud de una palabra con un carácter no ASCII?
py2>> len('¡no') #length of string=3, length of UTF-8 byte array=4, since with variable len encoding the non-ASCII chars = 2-6 bytes
4 #always gives bytes.len not str.len
Todo este tiempo pensaba que estaba pidiendo a la len de una cadena en AP2, que estaban recibiendo la longitud de la matriz de bytes de la codificación. Esa ambigüedad es el problema fundamental con las clases de doble tarea. ¿Qué versión de cualquier llamada a método implementas?
La buena noticia es que py3 soluciona este problema. Desenreda las clases str y bytes . La clase str tiene métodos similares a cadenas, la clase de bytes separada tiene métodos de matriz de bytes:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
Con suerte, saber esto ayuda a desmitificar el problema y hace que el dolor de la migración sea un poco más fácil de soportar.