plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wb") as outfile:
outfile.write(plaintext)
O código python acima está me dando o seguinte erro:
Traceback (most recent call last):
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 33, in <module>
compress_string()
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 15, in compress_string
outfile.write(plaintext)
File "C:\Python32\lib\gzip.py", line 312, in write
self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface
Respostas:
Se você usa o Python3x, então
string
não é o mesmo tipo do Python 2.x, deve convertê- lo em bytes (codificá-lo).Também não use nomes de variáveis como
string
oufile
enquanto esses são nomes de módulo ou função.EDIT @Tom
Sim, o texto não ASCII também é compactado / descompactado. Eu uso letras polonesas com codificação UTF-8:
fonte
str
) e vice-versa é desnecessária e corre o risco de decodificar erros ou incompatibilidades entre entrada e saída.Existe uma solução mais fácil para esse problema.
Você só precisa adicionar um
t
ao modo para que ele se tornewt
. Isso faz com que o Python abra o arquivo como um arquivo de texto e não como binário. Então tudo vai funcionar.O programa completo passa a ser o seguinte:
fonte
Você não pode serializar uma 'string' de Python 3 em bytes sem conversão explícita em alguma codificação.
é possivelmente o que você quer. Também funciona para python 2.xe 3.x.
fonte
Para o Python 3.x, você pode converter seu texto em bytes brutos através de:
Por exemplo:
O objeto retornado funcionará
outfile.write
.fonte
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 quandooutfile
é 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: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: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 é ?: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?
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:
Espero que isso ajude a desmistificar o problema e torne a dor da migração um pouco mais fácil de suportar.
fonte
Se você tiver uma idéia melhor, por favor me sugira ou sinta-se à vontade para me editar a qualquer momento aqui.
fonte
s.encode('utf-8')
tão pythônico comos.decode('utf-8')
na substituição des = bytes("s", "utf-8")
Para
Django
nosdjango.test.TestCase
testes de unidade, eu mudei de python2 sintaxe:Para usar a sintaxe do Python3
.decode('utf8')
:fonte