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)
Powyższy kod python daje mi następujący błąd:
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
Odpowiedzi:
Jeśli używasz Python3x,
string
to nie jest tego samego typu, co Python 2.x, musisz przerzucić go na bajty (zakodować).Nie używaj także nazw zmiennych, takich jak
string
lub,file
gdy są to nazwy modułów lub funkcji.EDYCJA @ Tom
Tak, tekst spoza ASCII jest również kompresowany / dekompresowany. Używam polskich liter z kodowaniem UTF-8:
źródło
str
) i wstecz jest niepotrzebna i grozi błędami dekodowania lub niedopasowaniem danych wejściowych i wyjściowych.Istnieje łatwiejsze rozwiązanie tego problemu.
Musisz tylko dodać
t
tryb, aby stał sięwt
. Powoduje to, że Python otwiera plik jako plik tekstowy, a nie binarny. Wtedy wszystko po prostu zadziała.Cały program wygląda następująco:
źródło
Nie można serializować „łańcucha” Python 3 do bajtów bez wyraźnej konwersji na niektóre kodowania.
jest prawdopodobnie tym, czego chcesz. Działa to również zarówno dla Pythona 2.x, jak i 3.x.
źródło
W przypadku Python 3.x możesz przekonwertować tekst na surowe bajty poprzez:
Na przykład:
Zwrócony obiekt będzie działał z
outfile.write
.źródło
Ten problem często występuje podczas przełączania z py2 na py3. W py2
plaintext
jest zarówno ciąg znaków, jak i tablica bajtów . W py3plaintext
jest tylko ciąg znaków , a metodaoutfile.write()
faktycznie pobiera tablicę bajtów, gdyoutfile
jest otwierana w trybie binarnym, więc zgłaszany jest wyjątek. Zmień dane wejściowe,plaintext.encode('utf-8')
aby rozwiązać problem. Czytaj dalej, jeśli ci to przeszkadza.W Py2 The zgłoszenie o file.write wykonane wydawać się zdałeś w ciąg:
file.write(str)
. Właściwie mijały w tablicy bajtów, trzeba było czytać deklarację takiego:file.write(bytes)
. Jeśli czytasz to tak, że problem jest prosty,file.write(bytes)
potrzebuje bajtów typ oraz w py3 aby uzyskać bajty z pomocą str go przekonwertować:Dlaczego dokumentacja py2 zadeklarowała
file.write
ciąg znaków? Dobrze w py2 rozróżnienie deklaracji nie miało znaczenia, ponieważ:Klasa str-bytes py2 ma metody / konstruktory, które sprawiają, że pod pewnymi względami zachowuje się jak klasa ciągów, a klasa tablicy bajtów w innych. Wygodne,
file.write
prawda ?:Dlaczego py3 złamał ten ładny system? Cóż, ponieważ w py2 podstawowe funkcje łańcuchowe nie działały dla reszty świata. Zmierzyć długość słowa ze znakiem innym niż ASCII?
Przez cały ten czas myślałeś, że pytasz o długość łańcucha w py2, uzyskiwałeś długość tablicy bajtów z kodowania. Ta dwuznaczność jest podstawowym problemem w przypadku klas podwójnego obciążenia. Którą wersję dowolnego wywołania metody implementujesz?
Dobra wiadomość jest taka, że py3 rozwiązuje ten problem. Rozplątuje klasy str i bajty . Str klasa ma sznuropodobne sposobach oddzielne bajtów klasa ma bajt metody tablicy:
Mam nadzieję, że wiedza o tym pomoże w tajemnicy problemu i sprawi, że ból związany z migracją będzie nieco łatwiejszy do zniesienia.
źródło
Cóż, jeśli jest to przydatne w przypadku usuwania irytującej postaci „b”. Jeśli ktoś ma lepszy pomysł, proszę zasugeruj mi lub możesz edytować mnie w dowolnym momencie tutaj. Jestem tylko początkującym
źródło
s.encode('utf-8')
tak pythonicznie jaks.decode('utf-8')
w zastępstwies = bytes("s", "utf-8")
Dla
Django
wdjango.test.TestCase
testowanie jednostkowe, zmieniłem python2 składnię:Aby użyć składni Python3
.decode('utf8')
:źródło