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 py3 plaintext
jest tylko ciąg znaków , a metoda outfile.write()
faktycznie pobiera tablicę bajtów, gdy outfile
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ć:
py3>> outfile.write(plaintext.encode('utf-8'))
Dlaczego dokumentacja py2 zadeklarowała file.write
ciąg znaków? Dobrze w py2 rozróżnienie deklaracji nie miało znaczenia, ponieważ:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
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 ?:
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
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?
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
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:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
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.