Ця проблема зазвичай виникає при переході від py2 до py3. У py2 plaintext
- це і рядок, і тип байтового масиву . У py3 plaintext
- це лише рядок , і метод outfile.write()
фактично приймає байтовий масив, коли outfile
він відкривається у двійковому режимі, тому виникає виняток. Змініть вхід на, plaintext.encode('utf-8')
щоб вирішити проблему. Читайте далі, якщо це вас турбує.
У PY2, то декларація file.write зробив це , схоже , як ви пройшли в рядку: file.write(str)
. На насправді ви проходили в масив байтів, ви повинні читали заяви на кшталт цього: file.write(bytes)
. Якщо ви читаєте це , як це проблема проста, file.write(bytes)
потребує байтах типу і в PY3 , щоб отримати байти з вул конвертування його:
py3>> outfile.write(plaintext.encode('utf-8'))
Чому документи py2 оголосили, що file.write
взяли рядок? Ну а в py2 відмінність декларації не мала значення, оскільки:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
Клас str-bytes py2 має методи / конструктори, які змушують його поводитись як клас рядків у деяких способах, а клас байтових масивів в інших. Зручно, file.write
чи не так ?:
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
Чому py3 зламав цю приємну систему? Тому що в py2 основні функції рядка не працювали для решти світу. Виміряйте довжину слова із символом, що не належить до 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
Весь цей час ви думали , що ви просили для Len рядки в PY2, ви отримуєте довжину масиву байт з кодування. Ця неоднозначність є основною проблемою для класів з подвійною службою. Яку версію будь-якого виклику методу ви реалізуєте?
Хороша новина тоді, що py3 вирішує цю проблему. Він роз'єднує класи str та bytes . Клас str має рядкоподібні методи, окремий клас байтів має методи байтового масиву:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
Сподіваємось, це знає, що допоможе демістифікувати проблему та полегшити міграційний біль трохи легше.