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 type de tableau d'octets . Dans py3 plaintext
est seulement une chaîne , et la méthode outfile.write()
prend en fait un tableau d'octets lorsqu'elle outfile
est ouverte en mode binaire, donc une exception est levée. Modifiez l'entrée plaintext.encode('utf-8')
pour résoudre le problème. Continuez à lire si cela vous dérange.
En py2, la déclaration de file.write fait croire que vous avez passé dans une chaîne: file.write(str)
. En fait , vous étiez de passage dans un tableau d'octets, vous devriez avoir été lu la déclaration comme ceci: file.write(bytes)
. Si vous le lisez comme ceci, le problème est simple, a file.write(bytes)
besoin d'un type d' octets et dans py3 pour obtenir des octets d'une chaîne, vous le convertissez:
py3>> outfile.write(plaintext.encode('utf-8'))
Pourquoi les documents py2 ont-ils déclaré avoir file.write
pris une chaîne? Eh bien dans py2, la distinction de déclaration n'a pas d'importance 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îne à certains égards et une classe de tableau d'octets à d'autres. Pratique pour file.write
non?:
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 joli système? Eh bien parce que dans py2, les fonctions de chaîne de base 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 que vous pensiez que vous demandiez l' len d'une chaîne dans py2, vous receviez la longueur du tableau d'octets du codage. Cette ambiguïté est le problème fondamental des classes à double droit. 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 bytes . La classe str a des méthodes de type chaîne, la classe d' octets séparée a des méthodes de tableau d'octets:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
Espérons que le savoir aide à démystifier le problème et rend la douleur migratoire un peu plus facile à supporter.