TypeError: 'str' ne supporte pas l'interface buffer

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) 

le code python ci-dessus me donne l'erreur suivante:

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:Python32libgzip.py", line 312, in write
    self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface
253
demandé sur bignose 2011-03-29 14:36:10

7 réponses

si vous utilisez Python3x alors string n'est pas le même type que pour Python 2.x, vous devez le convertir en octets (encoder).

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(bytes(plaintext, 'UTF-8'))

N'utilisez pas non plus de noms variables comme string ou file alors qu'il s'agit de noms de module ou de fonction.

EDIT @Tom

Oui, le texte non ASCII est aussi comprimé/décompressé. J'utilise des lettres polonaises avec L'encodage UTF-8:

plaintext = 'Polish text: ąćęłńóśźżĄĆĘŁŃÓŚŹŻ'
filename = 'foo.gz'
with gzip.open(filename, 'wb') as outfile:
    outfile.write(bytes(plaintext, 'UTF-8'))
with gzip.open(filename, 'r') as infile:
    outfile_content = infile.read().decode('UTF-8')
print(outfile_content)
283
répondu Michał Niklas 2015-10-05 00:03:15

il y a une solution plus facile à ce problème.

il suffit d'ajouter un t au mode pour qu'il devienne wt . Cela provoque Python pour ouvrir le fichier comme un fichier texte et non en binaire. Puis tout simplement.

le programme complet devient ceci:

plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wt") as outfile:
    outfile.write(plaintext)
90
répondu user1175849 2015-10-05 00:04:21

vous ne pouvez pas sérialiser une chaîne de Python 3 'en octets sans expliquer la conversion en un encodage.

outfile.write(plaintext.encode('utf-8'))

est peut-être ce que vous voulez. Cela fonctionne aussi pour python 2.x et 3.x.

41
répondu Andreas Jung 2015-10-05 00:04:59

Pour Python 3.x vous pouvez convertir votre texte en octets bruts par:

bytes("my data", "encoding")

par exemple:

bytes("attack at dawn", "utf-8")

l'objet retourné fonctionnera avec outfile.write .

27
répondu Skurmedel 2015-10-05 00:05:26

ce problème se produit fréquemment lors du passage de py2 à py3. Dans py2 plaintext est à la fois un chaîne et un tableau d'octets "1519170920 de type". Dans py3 plaintext est seulement une chaîne de caractères , et la méthode outfile.write() prend en fait un byte array quand outfile est ouvert en mode binaire, donc une exception est soulevée. Changez l'entrée en plaintext.encode('utf-8') pour corriger le problème. Lisez si cela vous dérange vous.

dans py2, la déclaration au dossier .écrivez comme si vous aviez passé dans une chaîne de caractères: file.write(str) . En fait vous passiez dans un tableau d'octets, vous auriez dû lire la déclaration comme ceci: file.write(bytes) . Si vous l'avez lu comme ça le problème est simple, file.write(bytes) a besoin d'un octets de type et dans py3 pour obtenir octets d'une str vous convertir:

py3>> outfile.write(plaintext.encode('utf-8'))

pourquoi le py2 docs a-t-il déclaré file.write a pris une ficelle? Eh bien dans py2 la distinction de déclaration n'a pas d'importance parce que:

py2>> str==bytes         #str and bytes aliased a single hybrid class in py2
True

la classe str-bytes de py2 a des méthodes/constructeurs qui la Font se comporter comme une classe de chaîne de caractères d'une certaine façon et une classe de tableau d'octets d'une autre manière. Pratique pour file.write n'est-ce pas?:

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

pourquoi py3 a-t-il brisé ce joli système? Eh bien, parce que dans py2 fonctions de base de chaîne ne fonctionnait pas pour le reste du monde. Mesurer la longueur d'un mot avec un caractère non-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

pendant tout ce temps, vous pensiez que vous demandiez le len d'une chaîne de caractères dans py2, vous obteniez la longueur du tableau des octets à partir de l'encodage. Cette ambiguïté est le problème fondamental des classes à double usage. Quelle version de n'importe quel appel de méthode implémentez-vous?

La bonne nouvelle est que py3 résout ce problème. Elle distingue les classes str et bytes . La classe str a des méthodes de type chaîne, la classe séparée bytes a des méthodes de tableau d'octets:

py3>> len('¡ok')       #string
3
py3>> len('¡ok'.encode('utf-8'))     #bytes
4

avec un peu de chance, savoir cela aide à démystifier la question, et rend la douleur de la migration un peu plus facile à supporter.

7
répondu Riaz Rizvi 2017-08-31 23:07:52
>>> s = bytes("s","utf-8")
>>> print(s)
b's'
>>> s = s.decode("utf-8")
>>> print(s)
s

bien si utile pour vous dans le cas de supprimer le caractère 'b' ennuyeux.Si quelqu'un a une meilleure idée s'il vous plaît me suggérer ou vous sentir libre de m'éditer n'importe quand ici.Je suis juste le nouveau

4
répondu Tapasit Suesasiton 2015-07-08 08:26:18

pour Django dans django.test.TestCase unit testing, j'ai changé ma syntaxe Python2 :

def test_view(self):
    response = self.client.get(reverse('myview'))
    self.assertIn(str(self.obj.id), response.content)
    ...

pour utiliser la Python3 .decode('utf8') syntaxe:

def test_view(self):
    response = self.client.get(reverse('myview'))
    self.assertIn(str(self.obj.id), response.content.decode('utf8'))
    ...
4
répondu Aaron Lelevier 2015-08-17 17:47:53