Sự khác biệt giữa mã hóa / giải mã là gì?


180

Tôi chưa bao giờ chắc chắn rằng tôi hiểu sự khác biệt giữa giải mã str / unicode và mã hóa.

Tôi biết rằng đó str().decode()là khi bạn có một chuỗi byte mà bạn biết có mã hóa ký tự nhất định, với tên mã hóa đó, nó sẽ trả về một chuỗi unicode.

Tôi biết rằng unicode().encode()chuyển đổi ký tự unicode thành một chuỗi byte theo một tên mã hóa nhất định.

Nhưng tôi không hiểu những gì str().encode()unicode().decode()là cho. Bất cứ ai có thể giải thích, và có thể sửa bất cứ điều gì khác mà tôi đã sai ở trên?

BIÊN TẬP:

Một số câu trả lời cung cấp thông tin về những gì .encodelàm trên một chuỗi, nhưng dường như không ai biết những gì .decodelàm cho unicode.


Tôi nghĩ rằng câu trả lời thứ hai của trang này là đủ rõ ràng và súc tích.
Ben

Câu trả lời:


106

Các decodephương pháp chuỗi unicode thực sự không có bất kì ứng dụng nào cả (trừ khi bạn có một số dữ liệu phi văn bản trong một chuỗi unicode vì một lý do - xem dưới đây). Nó chủ yếu ở đó vì lý do lịch sử, tôi nghĩ. Trong Python 3, nó hoàn toàn biến mất.

unicode().decode()sẽ thực hiện một tiềm ẩn mã hóa của sviệc sử dụng mặc định (ascii) codec. Xác nhận điều này như vậy:

>>> s = u'ö'
>>> s.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

>>> s.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

Các thông báo lỗi là hoàn toàn giống nhau.

Cho str().encode()đó là cách khác xung quanh - nó cố gắng một tiềm ẩn giải mã của svới mã hóa mặc định:

>>> s = 'ö'
>>> s.decode('utf-8')
u'\xf6'
>>> s.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)

Được sử dụng như thế này, str().encode()cũng là thừa.

Nhưng có một ứng dụng khác của phương thức sau rất hữu ích: có các mã hóa không liên quan gì đến các bộ ký tự và do đó có thể được áp dụng cho các chuỗi 8 bit theo cách có ý nghĩa:

>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'

Mặc dù vậy, bạn đã đúng: việc sử dụng "mã hóa" mơ hồ cho cả hai ứng dụng này là ... tuyệt vời. Một lần nữa, với các loại bytestringloại riêng biệt trong Python 3, đây không còn là vấn đề nữa.


4
.decode()trên chuỗi Unicode có thể hữu ích, ví dụ:print u'\\u0203'.decode('unicode-escape')
jfs 21/12/13

Ví dụ hay @JFSebastian trong python3 Tôi đoán bạn sẽ làm:print u'\\u0203'.encode('utf8').decode('unicode-escape')
AJP

1
@AJP: trên Python 3:codecs.decode(u'\\u0203', 'unicode-escape')
jfs

@hop: vâng. Để phát hiện đầu vào không hợp lệ và khả năng tương thích Python 2/3, chuỗi có thể được mã hóa rõ ràng bằng cách sử dụng asciimã hóa:\\u0203\u00e4'.encode('ascii').decode('unicode-escape')
jfs

@hop: bình luận đầu tiên của bạn (Tại sao bạn đã xóa nó? Đừng xóa những bình luận đã được trả lời) đã nói nó. Trả lời của tôi ( .encode('ascii').decode('unicode-escape')) không phụ thuộc vào sys.getdefaultencoding().
jfs

71

Để biểu diễn một chuỗi unicode dưới dạng một chuỗi byte được gọi là mã hóa . Sử dụng u'...'.encode(encoding).

Thí dụ:

    >>> u'æøå'.encode ('utf8')
    '\ xc3 \ x83 \ xc2 \ xa6 \ xc3 \ x83 \ xc2 \ xb8 \ xc3 \ x83 \ xc2 \ xa5'
    >>> u'æøå'.encode ('latin1')
    '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
    >>> u'æøå'.encode ('ascii')
    UnicodeEncodeError: 'ascii' codec không thể mã hóa các ký tự ở vị trí 0-5: 
    thứ tự không trong phạm vi (128)

Bạn thường mã hóa một chuỗi unicode bất cứ khi nào bạn cần sử dụng nó cho IO, ví dụ như chuyển nó qua mạng hoặc lưu nó vào một tệp đĩa.

Để chuyển đổi một chuỗi byte thành chuỗi unicode được gọi là giải mã . Sử dụng unicode('...', encoding)hoặc '...'. Giải mã (mã hóa).

Thí dụ:

   >>> u'æøå '
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5' # trình thông dịch in đối tượng unicode như vậy
   >>> unicode ('\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5', 'latin1')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
   >>> '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'.decode (' latin1 ')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'

Bạn thường giải mã một chuỗi byte bất cứ khi nào bạn nhận được dữ liệu chuỗi từ mạng hoặc từ tệp đĩa.

Tôi tin rằng có một số thay đổi trong xử lý unicode trong python 3, vì vậy những điều trên có lẽ không đúng với python 3.

Một số liên kết tốt:


6
Bạn đã không trả lời câu hỏi của OP. OP muốn biết str.encode () và unicode.decode () làm gì. Bạn chỉ cần lặp lại những gì đã được nêu trong câu hỏi ban đầu.
mắc kẹt vào

Câu trả lời tuyệt vời cho lý do tại sao trong thực tế, bạn đã từng gặp rắc rối với việc giải mã và mã hóa. Không phải mọi máy đều hiểu cùng một bộ ký tự, nhưng tất cả chúng đều hiểu byte. Mã hóa thành byte cho một ngôn ngữ máy tính hiểu toàn cầu (và có thể được chuyển hoặc lưu vào đĩa), nhưng giải mã khi con người thực sự phải đọc các byte đó (ví dụ: ở phía máy khách).
Alex Petralia

Câu trả lời tuyệt vời! Cái này nên đi lên !!
sandp

16

anUnicode. mã hóa ('mã hóa') dẫn đến một đối tượng chuỗi và có thể được gọi trên một đối tượng unicode

một chuỗi. giải mã ('mã hóa') dẫn đến một đối tượng unicode và có thể được gọi trên một chuỗi, được mã hóa theo mã hóa đã cho.


Một số giải thích thêm:

Bạn có thể tạo một số đối tượng unicode, không có bất kỳ bộ mã hóa nào. Cách nó được lưu trữ bởi Python trong bộ nhớ không phải là mối quan tâm của bạn. Bạn có thể tìm kiếm nó, phân tách nó và gọi bất kỳ chức năng thao tác chuỗi nào bạn muốn.

Nhưng đã đến lúc, khi bạn muốn in đối tượng unicode của mình lên bàn điều khiển hoặc vào một số tệp văn bản. Vì vậy, bạn phải mã hóa nó (ví dụ - trong UTF-8), bạn gọi mã hóa ('utf-8') và bạn nhận được một chuỗi có '\ u <someNumber>', có thể in hoàn toàn.

Sau đó, một lần nữa - bạn muốn làm ngược lại - đọc chuỗi được mã hóa bằng UTF-8 và coi nó là Unicode, vì vậy \ u360 sẽ là một ký tự, không phải 5. Sau đó, bạn giải mã một chuỗi (với mã hóa được chọn) và lấy đối tượng hoàn toàn mới của loại unicode.

Cũng như một ghi chú bên lề - bạn có thể chọn một số mã hóa biến thái, như 'zip', 'base64', 'rot' và một số trong số chúng sẽ chuyển đổi từ chuỗi sang chuỗi, nhưng tôi tin rằng trường hợp phổ biến nhất là trường hợp liên quan đến UTF-8 / UTF-16 và chuỗi.


12

mybytestring.encode (somecodec) có ý nghĩa đối với các giá trị sau của somecodec:

  • cơ sở64
  • bz2
  • zlib
  • lục giác
  • quopri
  • thối13
  • chuỗi_escape
  • uu

Tôi không chắc những gì giải mã một văn bản unicode đã được giải mã là tốt cho. Thử làm điều đó với bất kỳ mã hóa nào dường như luôn cố gắng mã hóa với mã hóa mặc định của hệ thống trước tiên.


5

Có một vài mã hóa có thể được sử dụng để khử / mã hóa từ str sang str hoặc từ unicode sang unicode. Ví dụ cơ sở64, hex hoặc thậm chí rot13. Chúng được liệt kê trong mô-đun codec .

Biên tập:

Thông báo giải mã trên chuỗi unicode có thể hoàn tác thao tác mã hóa tương ứng:

In [1]: u'0a'.decode('hex')
Out[1]: '\n'

Kiểu trả về là str thay vì unicode, điều không may theo quan điểm của tôi. Nhưng khi bạn không thực hiện một en- / giải mã thích hợp giữa str và unicode thì điều này trông giống như một mớ hỗn độn.


1
-1: Phương thức giải mã không được áp dụng cho đối tượng unicode. Thay vào đó, đối tượng unicode đang được mã hóa dưới dạng một 'ascii', trước khi hoạt động giải mã bắt đầu. Để chứng minh cho khẳng định đó, hãy thử u'ã'.decode ('hex') - mang lại UnicodeEncodeError
nosklo

2
@nosklo: Bạn nói đúng. Điều tôi thực sự muốn nói là các đối tượng unicode cũng có phương thức decode () để bạn cũng có thể áp dụng các codec không mã hóa ký tự cho chúng. Toàn bộ hoạt động kinh doanh không mã hóa ký tự này làm cho giao diện này trở nên lộn xộn trong Python <3.

1

Câu trả lời đơn giản là chúng trái ngược hoàn toàn với nhau.

Máy tính sử dụng đơn vị byte rất cơ bản để lưu trữ và xử lý thông tin; nó là vô nghĩa đối với mắt người.

Ví dụ: '\ xe4 \ xb8 \ xad \ xe6 \ x96 \ x87' là đại diện của hai ký tự Trung Quốc, nhưng máy tính chỉ biết (có nghĩa là in hoặc lưu trữ) đó là Ký tự Trung Quốc khi họ được cung cấp một từ điển để tìm Trong trường hợp này, từ tiếng Trung là từ điển "utf-8" và nó sẽ không hiển thị chính xác từ tiếng Trung dự định nếu bạn nhìn vào một từ điển khác hoặc sai (sử dụng phương pháp giải mã khác).

Trong trường hợp trên, quá trình cho một máy tính để tìm từ tiếng Trung là decode().

Và quá trình máy tính viết tiếng Trung vào bộ nhớ máy tính là encode().

Vì vậy, thông tin được mã hóa là các byte thô và thông tin được giải mã là các byte thô và tên của từ điển để tham chiếu (nhưng không phải là từ điển).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.