ปัญหานี้มักเกิดขึ้นเมื่อเปลี่ยนจาก py2 เป็น py3 ใน py2 plaintext
เป็นทั้งสตริงและชนิดอาร์เรย์แบบไบต์ ใน py3 plaintext
เป็นเพียงสตริงและวิธีการoutfile.write()
ใช้อาร์เรย์ไบต์จริงเมื่อoutfile
เปิดในโหมดไบนารีดังนั้นข้อยกเว้นจะเพิ่มขึ้น เปลี่ยนอินพุตเป็นplaintext.encode('utf-8')
เพื่อแก้ไขปัญหา อ่านต่อถ้าเรื่องนี้รบกวนคุณ
ใน py2 ที่ประกาศสำหรับ file.writefile.write(str)
ทำให้มันดูเหมือนคุณผ่านในสตริง: file.write(bytes)
ที่จริงคุณได้ผ่านในอาร์เรย์ไบต์ที่คุณควรจะได้รับการอ่านประกาศเช่นนี้: ถ้าคุณอ่านแบบนี้ปัญหานี้ง่ายfile.write(bytes)
ต้องใช้ชนิดไบต์และใน py3 เพื่อรับไบต์จากstr ที่คุณแปลง:
py3>> outfile.write(plaintext.encode('utf-8'))
เหตุใด py2 docs file.write
จึงประกาศใช้สตริง ใน py2 ความแตกต่างของการประกาศไม่สำคัญเพราะ:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
STR-ไบต์ชั้น 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และไบต์ STRชั้นจะมีสตริงเหมือนวิธีการแยกไบต์ชั้นมีวิธีการอาร์เรย์ไบต์:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
หวังว่าการรู้ว่าสิ่งนี้จะช่วยลดความน่าสงสัยของปัญหาและทำให้ความเจ็บปวดจากการย้ายถิ่นฐานง่ายขึ้นเล็กน้อย