Question TypeError: 'str' ne supporte pas l'interface tampon


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:\Python32\lib\gzip.py", line 312, in write
    self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface

250
2018-03-29 10:36


origine


Réponses:


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

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 de variables comme string ou file alors que ce sont des noms de module ou de fonction.

EDIT @Tom

Oui, le texte non ASCII est également compressé / décompressé. J'utilise des lettres polonaises avec un codage 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)

281
2018-03-29 10:51



Il existe une solution plus facile à ce problème.

Vous avez juste besoin d'ajouter un t au mode de sorte qu'il devient wt. Cela provoque Python pour ouvrir le fichier en tant que fichier texte et non binaire. Alors tout va juste fonctionner.

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
2017-07-21 08:07



Vous ne pouvez pas sérialiser une chaîne 'Python 3' en octets sans conversion explicite en un encodage.

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

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


41
2018-03-29 10:44



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

bytes("my data", "encoding")

Par exemple:

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

L'objet retourné travaillera avec outfile.write.


26
2018-03-29 10:45



Ce problème se produit généralement lors du passage de py2 à py3. Dans py2 plaintext est à la fois un chaîne et un tableau d'octets type. En py3 plaintext est seulement un chaîneet la méthode outfile.write() prend en fait un tableau d'octets quand outfile est ouvert en mode binaire, donc une exception est levée. Changer l'entrée à plaintext.encode('utf-8') pour résoudre le problème. Continuez à lire si cela vous dérange.

En py2, le déclaration pour file.write fait croire que vous avez passé dans une chaîne: file.write(str). En fait, vous passiez dans un tableau d'octets, vous devriez avoir lu la déclaration comme ceci: file.write(bytes). Si vous le lisez comme ça, le problème est simple, file.write(bytes) a besoin d'un octets tapez et dans py3 pour obtenir octets sur un str vous le convertissez:

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

Pourquoi les docs py2 ont-ils déclaré file.write a pris une ficelle? Eh bien, en py2, la distinction de déclaration n'avait pas d'importance parce que:

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

le str-octets La classe de py2 a des méthodes / constructeurs qui lui permettent de se comporter comme une classe de chaîne à certains égards et une classe de tableau d’octets dans d’autres. 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 beau système? Parce que dans py2, les fonctions de base de la chaîne ne fonctionnaient 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 len d'une chaîne dans py2, vous obteniez la longueur du tableau d'octets de l'encodage. Cette ambiguïté est le problème fondamental des classes à double fonction. Quelle version de n'importe quel appel de méthode implémentez-vous?

La bonne nouvelle est que py3 résout ce problème. Il démêle le str et octets Des classes. le str classe a des méthodes semblables à des chaînes, la séparation octets La classe a des méthodes de tableau d'octets:

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

Nous espérons que cela vous aidera à démystifier le problème et à rendre la migration plus difficile à supporter.


7
2018-01-09 00:43



>>> s = bytes("s","utf-8")
>>> print(s)
b's'
>>> s = s.decode("utf-8")
>>> print(s)
s

Eh bien, si utile pour vous dans le cas de suppression caractère b ennuyeux.Si quelqu'un a une meilleure idée s'il vous plaît me suggérer ou n'hésitez pas à me modifier à tout moment ici.Je suis juste newbie


4
2017-07-08 08:26



Pour Django dans django.test.TestCase tests unitaires, j'ai changé mon Python2 syntaxe:

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

Pour utiliser le 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
2017-08-17 17:47