Esse problema geralmente ocorre ao mudar de py2 para py3. Em py2 plaintext
há um tipo de string e um array de bytes . No py3, plaintext
é apenas uma string , e o método, outfile.write()
na verdade, utiliza uma matriz de bytes quando outfile
é aberto no modo binário, portanto, uma exceção é gerada. Mude a entrada paraplaintext.encode('utf-8')
para corrigir o problema. Leia se isso lhe incomoda.
Em PY2, a declaração para file.write fez parecer que você passou em uma string: file.write(str)
. Na verdade você estava passando em um array de bytes, você deve ter lido a declaração como esta: file.write(bytes)
. Se você lê assim, o problema é simples, file.write(bytes)
precisa de um tipo de bytes e, em py3, para obter bytes de um str, você o converte:
py3>> outfile.write(plaintext.encode('utf-8'))
Por que os documentos py2 declararam que file.write
levou uma string? Bem, no py2 a distinção de declaração não importava porque:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
A classe str-bytes do py2 possui métodos / construtores que fazem com que se comporte como uma classe de strings de algumas maneiras e uma classe de matriz de bytes em outras. Conveniente para file.write
não é ?:
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 que o py3 quebrou esse bom sistema? Bem, porque no py2, as funções básicas de string não funcionavam no resto do mundo. Mede o comprimento de uma palavra com um caractere não 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
Durante todo esse tempo, você pensou que estava pedindo o len de uma string em py2, estava obtendo o comprimento da matriz de bytes da codificação. Essa ambiguidade é o problema fundamental das classes de serviço duplo. Qual versão de qualquer chamada de método você implementa?
A boa notícia é que o py3 corrige esse problema. Desembaraça as classes str e bytes . A classe str possui métodos semelhantes a strings, a classe bytes separados possui métodos de matriz de bytes:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
Espero que isso ajude a desmistificar o problema e torne a dor da migração um pouco mais fácil de suportar.