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
Si vous utilisez Python3x, alors string
n'est pas du même type que pour Python 2.x, vous devez le convertir en octets (l'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'))
De même, n'utilisez pas de noms de variables tels que string
ou file
, car il s'agit de noms de module ou de fonction.
EDIT @Tom
Oui, le texte non-ASCII est également compressé/décompressé. J'utilise des lettres polonaises avec le 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)
Il existe une solution plus facile à ce problème.
Vous devez simplement ajouter un t
au mode pour qu'il devienne wt
. Ainsi, Python ouvre le fichier en tant que fichier texte et non binaire. Ensuite, tout fonctionnera.
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)
Vous ne pouvez pas sérialiser une chaîne Python 3 en octets sans une conversion explicite en un codage.
outfile.write(plaintext.encode('utf-8'))
est peut-être ce que vous voulez. Cela fonctionne également pour python 2.x et 3.x.
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é fonctionnera avec outfile.write
.
Ce problème se produit généralement lors du passage de py2 à py3. Dans py2, plaintext
est à la fois une chaîne et un tableau type. Dans py3, plaintext
n’est qu’une chaîne et la méthode outfile.write()
prend en réalité un . tableau d'octets lorsque outfile
est ouvert en mode binaire, une exception est donc déclenchée. Modifiez l'entrée en plaintext.encode('utf-8')
pour résoudre le problème. Continuez à lire si cela vous dérange.
Dans py2, le déclaration de file.write donnait l'impression que vous aviez passé une chaîne: 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 le lisez ainsi, le problème est simple, file.write(bytes)
a besoin d'un type octets et en py3 pour obtenir octets sur un str vous le convertissez:
py3>> outfile.write(plaintext.encode('utf-8'))
Pourquoi les documents py2 ont-ils déclaré file.write
pris une chaîne? Dans py2, la distinction de déclaration importait peu car:
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înes d'une certaine manière et une classe de tableau d'octets 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 cassé ce système de Nice? Eh bien, car dans py2, les fonctions de base des chaînes 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 demander le len d'une chaîne en py2, vous obteniez la longueur du tableau d'octets à partir de l'encodage. Cette ambiguïté est le problème fondamental des classes à double tâche. Quelle version d'un appel de méthode implémentez-vous?
La bonne nouvelle est que py3 résout ce problème. Il démêle les classes str et octets . La classe str a des méthodes de type chaîne, la classe séparée octets a méthodes de tableau d'octets:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
J'espère que le fait de savoir que cela aide à résoudre le problème et rend la douleur liée à la migration un peu plus facile à supporter.
Pour Django
dans le test d'unité Django.test.TestCase
, j'ai modifié ma syntaxe Python2:
def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content)
...
Pour utiliser la syntaxe Python.decode('utf8')
:
def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content.decode('utf8'))
...
>>> s = bytes("s","utf-8")
>>> print(s)
b's'
>>> s = s.decode("utf-8")
>>> print(s)
s
Bien si utile pour vous en cas de suppression du caractère 'b' agaçant. Si quelqu'un a une meilleure idée s'il vous plaît suggérez-moi ou n'hésitez pas à me modifier à tout moment ici.Je suis juste un débutant