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)
El código de Python anterior me está dando el siguiente error:
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
Respuestas:
Si usa Python3x, entonces
string
no es del mismo tipo que para Python 2.x, debe convertirlo a bytes (codificarlo).Tampoco use nombres de variables como
string
ofile
mientras esos son nombres de módulo o función.EDITAR @Tom
Sí, el texto no ASCII también está comprimido / descomprimido. Yo uso letras polacas con codificación UTF-8:
fuente
str
) y viceversa es innecesaria, y corre el riesgo de decodificar errores o desajustes entre la entrada y la salida.Hay una solución más fácil para este problema.
Solo necesita agregar
t
a al modo para que se conviertawt
. Esto hace que Python abra el archivo como un archivo de texto y no como binario. Entonces todo simplemente funcionará.El programa completo se convierte en esto:
fuente
No puede serializar una 'cadena' de Python 3 a bytes sin una conversión explícita a alguna codificación.
Es posiblemente lo que quieres. También esto funciona tanto para python 2.xy 3.x.
fuente
Para Python 3.x puede convertir su texto a bytes sin procesar a través de:
Por ejemplo:
El objeto devuelto funcionará con
outfile.write
.fuente
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 py3plaintext
es solo una cadena , y el métodooutfile.write()
realmente toma una matriz de bytes cuandooutfile
se abre en modo binario, por lo que se genera una excepción. Cambie la entrada aplaintext.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:¿Por qué los documentos de py2 declararon
file.write
tomar una cadena? Bueno, en py2 la distinción de declaración no importaba porque: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í ?:¿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?
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:
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.
fuente
Bueno, si es útil para usted en caso de eliminar el molesto carácter 'b'. Si alguien tiene una mejor idea, sugiérame o siéntase libre de editarme en cualquier momento aquí. Solo soy un novato
fuente
s.encode('utf-8')
tan pitónico comos.decode('utf-8')
en reemplazo des = bytes("s", "utf-8")
Para
Django
endjango.test.TestCase
la unidad de pruebas, he cambiado de python2 sintaxis:Para usar el Python3
.decode('utf8')
sintaxis de :fuente