Làm cách nào để giải mã trong python 3?

Có thể cho rằng các tính năng mới quan trọng nhất được giới thiệu trong Python 3 là triển khai mới của str dưới dạng Unicode theo mặc định và sự tách biệt nghiêm ngặt giữa dữ liệu văn bản và dữ liệu nhị phân

Cả hai đều hết lòng chào đón những thay đổi. Đặc biệt, quyết định mặc định Unicode đã giúp loại bỏ rất nhiều rắc rối trong công việc hàng ngày của chúng tôi với tư cách là nhà phát triển (ai đã nói UnicodeError?). Tuy nhiên, vẫn còn một số nhầm lẫn về thay đổi này, vì vậy hãy thử làm sáng tỏ điều hoàn toàn mới này

Một Chút Lịch Sử

TL; DR Máy tính chuyển đổi các ký tự thành số theo ánh xạ được công nhận rộng rãi có tên là Unicode. Unicode là siêu bộ của một ánh xạ cũ hơn nhưng vẫn thực tế được gọi là ASCII. Các số này được lưu trong bộ nhớ và thành tệp theo nhiều tiêu chuẩn khác nhau được gọi là bảng mã. Phổ biến nhất và trong số các bảng mã này là UTF-8

Có rất nhiều bài viết thú vị trên Internet về lý do đằng sau ASCII và Unicode, và bạn có thể muốn xem chúng nếu muốn tìm hiểu sâu hơn về toàn bộ câu chuyện. Hãy làm tổng quan nhanh để hiểu rõ hơn các vấn đề hiện tại

Ngày xưa, việc lưu văn bản trên máy tính dễ dàng như chuyển đổi từng ký tự thành một số từ 0 đến 127, tức là bảy bit không gian. Điều đó đủ để lưu trữ tất cả các số, chữ cái, dấu chấm câu và ký tự điều khiển mà một người viết tiếng Anh trung bình cần. Ánh xạ này là một tiêu chuẩn đã được thống nhất gọi là

Hầu hết các máy tính vào thời điểm đó đều sử dụng tám bit cho một byte, nghĩa là có thêm một số dung lượng trống cho một bộ bổ sung gồm 128 ký tự nữa. Vấn đề là, phạm vi phổ trên ASCII tiêu chuẩn này khá miễn phí, vì vậy các tổ chức khác nhau bắt đầu sử dụng nó cho các mục đích khác nhau. Điều này dẫn đến một mớ hỗn độn khổng lồ gồm các bảng ký tự khác nhau trong đó các số giống nhau đại diện cho các chữ cái khác nhau trong các bảng chữ cái khác nhau. Việc chia sẻ tài liệu văn bản trở nên lộn xộn, chưa kể đến bảng chữ cái châu Á với hàng ngàn chữ cái, không thể vừa với không gian 256 ký hiệu này.

Đó là nơi Unicode đến để trợ giúp. Một nỗ lực to lớn đã bắt đầu để ánh xạ từng ký tự và biểu tượng mà nhân loại biết đến thành một tập hợp được gọi là điểm mã, tức là một số thập lục phân đại diện cho biểu tượng đó. Vì vậy, tập đoàn Unicode đã quyết định rằng chữ cái tiếng Anh 'Q' là U+0055, chữ cái Latinh 'è' là U+00E8, chữ cái Cyrillic 'й' là U+0439, ký hiệu toán học '√' là U+221A, . Bạn thậm chí có thể tìm thấy một hình tượng cho một đống phân. Vì lý do tương thích, 128 số đầu tiên ánh xạ các ký tự giống như ASCII

Bây giờ, vì tất cả chúng ta đã đồng ý gán một số duy nhất cho mỗi và mọi glyph từng được hình thành, và cho rằng có hàng ngàn trên hàng ngàn biểu tượng như vậy được ánh xạ, làm thế nào để chúng ta lưu trữ các điểm mã đó trong máy tính?

Tóm lại, các mã hóa khác nhau đã được phát minh để chuyển đổi các điểm mã thành byte, nhưng một trong số chúng được cho là tốt nhất và được sử dụng nhiều nhất. UTF-8. Đây là tiêu chuẩn vàng hiện tại của bảng mã Unicode. Trừ khi bạn biết mình đang làm gì, rất có thể bạn không muốn sử dụng bất cứ thứ gì khác

Không có chuỗi nào không có mã hóa

Nếu bạn đã theo dõi cuộc thảo luận cho đến giờ, có lẽ bạn đã nắm được một điểm quan trọng về việc lưu và đọc văn bản trên máy tính

Có một chuỗi mà không biết mã hóa của nó chẳng có ý nghĩa gì cả

Bạn chỉ đơn giản là không thể diễn giải và giải mã một chuỗi trừ khi bạn biết mã hóa của nó. Và, mặc dù chúng tôi đã quyết định rằng UTF-8 là tiêu chuẩn vàng của giải mã Unicode, nhưng bạn có thể gặp các bảng mã khác trong công việc của mình với tư cách là một lập trình viên và sẽ cần phải hành động tương ứng

Nếu bạn đã từng tìm thấy các ký tự lạ trong nội dung email hoặc trên một trang web, thì đó là do email hoặc trang web đó không khai báo mã hóa, vì vậy ứng dụng thư khách hoặc trình duyệt của bạn đang cố đoán mã hóa và không thể đoán được mã hóa đó

Trang Wikipedia tiếng Tây Ban Nha về Unicode do Google Chrome tải với mã hóa sai cố ý. Lưu ý cách các ký tự có dấu được giải mã và hiển thị kém vì Chrome đang cố giải mã sai cách các điểm mã trên 127

Vậy còn Unicode trên Python 3 thì sao?

Các chuỗi khá lộn xộn trong Python 2. Loại mặc định cho chuỗi là str, nhưng nó được lưu dưới dạng bytes. Nếu bạn cần lưu các chuỗi Unicode trong Python 2, bạn phải sử dụng một loại khác có tên là unicode, thường thêm một ____6_______ vào chính chuỗi đó khi tạo. Sự kết hợp giữa bytesunicode trong Python 2 thậm chí còn khó khăn hơn, vì Python cho phép ép buộc và bỏ ẩn khi trộn các loại khác nhau. Điều đó có thể dễ dàng thực hiện được và rõ ràng là rất tuyệt, nhưng hầu hết thời gian nó chỉ gây đau đầu khi chạy

Tất cả điều này đã trở nên tốt đẹp với Python 3. Chúng tôi có hai loại khác nhau và được phân tách nghiêm ngặt ở đây

  1. str tương ứng với loại unicode trước đây trên Python 2. Nó được thể hiện bên trong dưới dạng một chuỗi các điểm mã Unicode. Bạn có thể khai báo một biến str mà không cần thêm chuỗi với ____6_______ vào trước, bởi vì bây giờ nó là mặc định
  2. str3 gần tương ứng với loại str trước đây (đối với phần bytes) trên Python 2. Đây là định dạng tuần tự hóa nhị phân được biểu thị bằng một chuỗi các số nguyên 8 bit phù hợp để lưu trữ dữ liệu trên hệ thống tệp hoặc gửi dữ liệu qua Internet. Đó là lý do tại sao bạn chỉ có thể tạo bytes chứa các ký tự chữ ASCII. Để xác định một biến byte, chỉ cần thêm một str7 vào chuỗi

strbytes có một bộ phương thức hoàn toàn khác. Bạn không thể nối hoặc trộn chúng theo bất kỳ cách nào

Bạn buộc phải giữ mọi thứ thẳng thắn, và đó là một điều thực sự tốt. Trong Python 3, mã không thành công ngay lập tức nếu bạn làm việc không tốt và điều đó giúp tiết kiệm rất nhiều phiên sửa lỗi sau này. Tuy nhiên, có một mối quan hệ chặt chẽ giữa strbytes, vì vậy Python cho phép bạn chuyển đổi loại bằng hai phương thức chuyên dụng

  1. str có thể được mã hóa thành bytes bằng cách sử dụng phương thức encode()
  2. bytes có thể được giải mã thành str bằng cách sử dụng phương thức decode()

Cả hai phương thức đều chấp nhận một tham số, đó là mã hóa được sử dụng để mã hóa hoặc giải mã. Mặc định cho cả hai là UTF-8

Lưu ý cách các chuỗi bytes được thêm b vào trước khi được in trên trình thông dịch Python

Một bức tranh đáng giá ngàn lời nói, vì vậy

Loại bytes không có mã hóa vốn có, vì vậy bạn phải biết mã hóa nếu muốn thử và giải mã nó, như chúng ta đã thấy một vài đoạn ở trên. Lại. bạn không thể giả vờ giải mã thứ gì đó trừ khi bạn biết mã hóa của nó

Hơn nữa, không có cách nào để suy ra mã hóa mà một bytes có. Đây là điều bạn phải tính đến khi làm việc với dữ liệu đến từ Internet hoặc từ một tệp mà bạn không tạo. Thật vậy, những điều kỳ lạ xảy ra khi bạn giải mã một bytes bằng một mã hóa khác với mã hóa mà bạn đã sử dụng để mã hóa từ str, giống như chúng ta đã thấy với trang Wikipedia tiếng Tây Ban Nha

Ký hiệu € được mã hóa bằng UTF-8 bị chuyển đổi ngược trở lại nếu bạn giải mã bằng mã hóa khác

Truy cập tệp trên Python 3

Như bạn có thể tưởng tượng, điều này có hậu quả rất lớn đối với quá trình ghi và đọc tệp (hoặc các dạng đầu vào khác) trên Python 3

Trong Python 3, đọc tệp ở chế độ str1 có nghĩa là giải mã dữ liệu thành Unicode và nhận đối tượng str. Đọc tệp ở chế độ str3 có nghĩa là đọc dữ liệu nguyên trạng, không giải mã ngầm và lưu dưới dạng bytes

Vì lý do tương tự, giao diện phương thức str5 đã thay đổi kể từ Python 2 và giờ đây nó chấp nhận một tham số mã hóa. Nếu bạn đọc kỹ, bạn sẽ hiểu rằng tham số này chỉ có giá trị khi sử dụng chế độ str1, nơi Python giải mã dữ liệu thành Unicode, và nó vô dụng trong chế độ str3

Điều quan trọng là phải hiểu rằng Python không cố gắng đoán mã hóa. Thay vào đó, nó sử dụng mã hóa được trả về từ str8. Nếu bạn không truyền tham số mà chỉ dựa vào giá trị mặc định và thấy những điều kỳ lạ, rất có thể phương thức đó đang trả về mã hóa sai cho dữ liệu của bạn. Lại. không mã hóa, không tiệc tùng

Các phương pháp hay nhất và khắc phục sự cố với Unicode trên Python3

Bánh mì Unicode

Ned Batchhelder vĩ đại đã có một bài nói/bài báo tuyệt vời mà tôi hết lòng giới thiệu nếu bạn thường xuyên phải làm việc với các chuỗi trong Python 3. Trong buổi nói chuyện này, anh ấy đã đặt ra thuật ngữ Unicode Sandwich để đặt tên cho một phương pháp tuyệt vời khi xử lý các chuỗi văn bản trong Python. Sử dụng các từ của riêng mình, cách tiếp cận được đề xuất là

“Byte ở bên ngoài, unicode ở bên trong, mã hóa/giải mã ở các cạnh. ”

Ý tưởng là sử dụng một đối tượng str khi xử lý văn bản, do đó có quyền truy cập vào nhiều phương thức mà Python cung cấp để xử lý chuỗi. Tuy nhiên, khi bạn đang xử lý các nội dung bên ngoài như API, hãy truy cập bytes. Cách tiếp cận này tuyệt vời đến mức một số thư viện thậm chí có thể tóm tắt toàn bộ quy trình từ bạn và cho phép nhập/xuất Unicode, chuyển đổi tất cả thành str trong nội bộ

2 * 3 = sáu

Vẫn có một cơ sở mã lớn gồm các chương trình Python 2 và một số thư viện vẫn hỗ trợ cả Py2 và Py3 theo một cách khác, ngay cả trong cùng một phiên bản

Benjamin Peterson đã phát triển một thư viện tương thích tuyệt vời có tên là six cung cấp các chức năng để bao bọc sự khác biệt giữa hai phiên bản Python chính. Như bạn có thể tưởng tượng, nó cũng có rất nhiều thứ để quản lý chuỗi. Bạn có thể muốn kiểm tra nó và xem nó có thể giúp bạn phát triển mã tương thích chéo như thế nào

Không trộn lẫn str và byte

Hầu hết các lỗi phát sinh khi xử lý chuỗi là do cố gắng trộn lẫn giữa strbytes. Điều này có lẽ điển hình hơn nếu bạn đã trải nghiệm Python thành thạo trong 2. x, nơi ranh giới giữa hai loại ngày càng mờ nhạt. Nếu bạn vẫn gặp lỗi như

TypeError: a bytes-like object is required, not 'str'

và tương tự, hãy kiểm tra xem bạn có đang sử dụng đúng phương pháp trên đúng đối tượng không. Ngoài ra, hãy kiểm tra xem bạn đã mở tệp đúng cách theo nhu cầu của mình chưa. Thật dễ dàng thất bại trong bài kiểm tra ngăn chặn đã hoạt động trong nhiều năm trên Python 2

Điều kiện bytes4 trên dòng một không thành công vì chúng tôi đã mở tệp ở chế độ nhị phân và sau đó yêu cầu Python đối chiếu một chuỗi với đối tượng bytes. Mở tệp ở chế độ đọc hoặc thậm chí giải mã bytes thành str sẽ hoạt động tốt

Biết mã hóa của bạn

Hãy để tôi nhấn mạnh khái niệm này một lần nữa. bạn không thể giả vờ giải mã bytes nếu bạn không biết mã hóa. Thông tin này không thể được suy ra một cách đáng tin cậy từ chính các byte và bạn cần lấy hoặc chia sẻ thông tin đó nếu bạn đang thực hiện I/O với các tệp hoặc API mà bạn không kiểm soát. Như chúng ta đã thấy trước đây, rất có thể Python sẽ giải mã bytes của bạn nếu bạn chuyển mã sai cho nó, nhưng bạn có thể sẽ nhận được rác

Đoạn thưởng. io. chuỗiIO và io. byteIO

Liên quan chặt chẽ đến những thay đổi lớn về chuỗi mà chúng ta vừa thấy là một thay đổi khác liên quan đến các mô-đun Python2 trước đây là unicode0 và unicode1

Ngoài những khác biệt nhỏ về API và hiệu suất giữa hai mô-đun, unicode0 và unicode1 dựa trên cách tiếp cận của Py2 đối với quản lý chuỗi, chấp nhận chuỗi Unicode hoặc chuỗi byte. Vì Py3 có cách tiếp cận hoàn toàn khác nên hai mô-đun này đã bị xóa và thay thế bằng hai lớp mới bên trong mô-đun unicode4. Cách sử dụng của chúng khá đơn giản

  1. unicode5 chấp nhận một chuỗi byte làm đối số
  2. unicode6 chấp nhận chuỗi Unicode và mã hóa làm đối số

Đơn giản như thế. Chúng trả về hai đối tượng giống như tệp mà bạn có thể sử dụng như bình thường và theo mô hình bánh sandwich. Bạn có thể đọc thêm về cả hai trong tài liệu chính thức

Phương thức giải mã trong Python 3 là gì?

Python 3 - Phương thức giải mã chuỗi () . Nó mặc định là mã hóa chuỗi mặc định. decodes the string using the codec registered for encoding. It defaults to the default string encoding.

Làm cách nào để giải mã mã Python?

decode() là một phương thức được chỉ định trong Chuỗi trong Python 2. Phương pháp này được sử dụng để chuyển đổi từ một lược đồ mã hóa, trong đó chuỗi đối số được mã hóa thành lược đồ mã hóa mong muốn. Điều này hoạt động ngược lại với mã hóa. Nó chấp nhận mã hóa của chuỗi mã hóa để giải mã nó và trả về chuỗi gốc.

Cách giải mã chuỗi thành UTF

Giải mã các byte được mã hóa UTF-8 thành str. bs. giải mã ('utf-8')
Mã hóa chuỗi thành byte UTF-8. S. mã hóa ('utf-8')

Mã hóa () trong Python3 là gì?

Phương thức encode() trả về phiên bản được mã hóa của chuỗi . Mã hóa mặc định là mã hóa chuỗi mặc định hiện tại. Các lỗi có thể được đưa ra để thiết lập một sơ đồ xử lý lỗi khác.