Apa perbedaan antara encode / decode?

180

Saya tidak pernah yakin bahwa saya mengerti perbedaan antara str / unicode decode dan encode.

Saya tahu itu str().decode()untuk ketika Anda memiliki string byte yang Anda tahu memiliki pengkodean karakter tertentu, mengingat nama pengkodean itu akan mengembalikan string unicode.

Saya tahu bahwa unicode().encode()mengubah karakter unicode menjadi serangkaian byte sesuai dengan nama penyandian yang diberikan.

Tapi saya tidak mengerti apa str().encode()dan unicode().decode()untuk apa. Adakah yang bisa menjelaskan, dan mungkin juga mengoreksi hal lain yang saya salah di atas?

EDIT:

Beberapa jawaban memberikan info tentang apa yang .encodedilakukan pada string, tetapi tidak ada yang tahu apa yang .decodedilakukan untuk unicode.

ʞɔıu
sumber
Saya pikir jawaban kedua halaman ini cukup jelas dan ringkas.
Ben

Jawaban:

106

The decodeMetode string unicode benar-benar tidak memiliki aplikasi sama sekali (kecuali jika Anda memiliki beberapa data non-teks dalam string unicode untuk beberapa alasan - lihat di bawah). Itu terutama ada karena alasan historis, saya pikir. Dalam Python 3 itu benar-benar hilang.

unicode().decode()akan melakukan implisit encoding dari smenggunakan default (ascii) codec. Verifikasi seperti ini:

>>> 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)

Pesan kesalahannya persis sama.

Untuk str().encode()itu sebaliknya - ia mencoba implisit decoding dari sdengan encoding default:

>>> 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)

Digunakan seperti ini, str().encode()juga berlebihan.

Tetapi ada aplikasi lain dari metode terakhir yang berguna: ada penyandian yang tidak ada hubungannya dengan set karakter, dan dengan demikian dapat diterapkan ke string 8-bit dengan cara yang bermakna:

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

Anda benar, meskipun: penggunaan "encoding" yang ambigu untuk kedua aplikasi ini adalah ... awkard. Sekali lagi, dengan terpisah bytedan stringmengetikkan Python 3, ini tidak lagi menjadi masalah.


sumber
4
.decode()pada string Unicode mungkin berguna misalnya,print u'\\u0203'.decode('unicode-escape')
jfs
Contoh yang bagus @JFSebastian di python3 Saya kira Anda akan melakukannya:print u'\\u0203'.encode('utf8').decode('unicode-escape')
AJP
1
@AJP: di Python 3:codecs.decode(u'\\u0203', 'unicode-escape')
jfs
@hop: ya. Untuk mendeteksi input yang tidak valid dan untuk kompatibilitas Python 2/3, string dapat dikodekan secara eksplisit menggunakan asciipengkodean:\\u0203\u00e4'.encode('ascii').decode('unicode-escape')
jfs
@hop: komentar pertama Anda (Mengapa Anda menghapusnya? Jangan menghapus komentar yang telah dibalas) sudah mengatakannya. Balasan saya ( .encode('ascii').decode('unicode-escape')) tidak bergantung pada sys.getdefaultencoding().
jfs
71

Untuk mewakili string unicode sebagai string byte dikenal sebagai pengodean . Gunakan u'...'.encode(encoding).

Contoh:

    >>> 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: codec 'ascii' tidak dapat menyandikan karakter di posisi 0-5: 
    ordinal tidak dalam jangkauan (128)

Anda biasanya menyandikan string unicode kapan pun Anda perlu menggunakannya untuk IO, misalnya mentransfernya melalui jaringan, atau menyimpannya ke file disk.

Untuk mengkonversi string byte ke string unicode dikenal sebagai decoding . Gunakan unicode('...', encoding)atau '...'. Decode (pengodean).

Contoh:

   >>> u'æøå '
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5' # interpreter mencetak objek unicode seperti itu
   >>> unicode ('\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5', 'latin1')
   kamu '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
   >>> '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'.decode (' latin1 ')
   kamu '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'

Anda biasanya mendekode string byte setiap kali Anda menerima data string dari jaringan atau dari file disk.

Saya percaya ada beberapa perubahan dalam penanganan unicode di python 3, jadi di atas mungkin tidak benar untuk python 3.

Beberapa tautan bagus:

kode kode
sumber
6
Anda tidak menjawab pertanyaan OP. OP ingin tahu apa yang dilakukan str.encode () dan unicode.decode (). Anda baru saja mengulangi apa yang dinyatakan dalam pertanyaan awal.
stuckintheshuck
Jawaban yang bagus untuk alasan mengapa dalam praktiknya Anda akan dipusingkan dengan decoding dan encoding. Tidak setiap mesin memahami set karakter yang sama, tetapi mereka semua mengerti byte. Menyandikan ke dalam byte untuk bahasa yang secara universal dipahami oleh komputer (dan dapat ditransfer atau disimpan ke disk), tetapi dekode ketika manusia benar-benar harus membaca byte tersebut (mis. Di sisi klien).
Alex Petralia
Jawaban yang fantastis! Ini harusnya naik !!
sandyp
16

anUnicode. encode ('encoding') menghasilkan objek string dan dapat dipanggil pada objek unicode

Sebuah benang. decode ('encoding') menghasilkan objek unicode dan dapat dipanggil pada string, dikodekan dalam pengkodean yang diberikan.


Beberapa penjelasan lagi:

Anda dapat membuat beberapa objek unicode, yang tidak memiliki set penyandian. Cara itu disimpan oleh Python dalam memori bukan urusan Anda. Anda dapat mencarinya, membaginya dan memanggil fungsi memanipulasi string yang Anda suka.

Tetapi ada saatnya, ketika Anda ingin mencetak objek unicode Anda ke konsol atau ke beberapa file teks. Jadi, Anda harus menyandikannya (misalnya - dalam UTF-8), Anda memanggil penyandian ('utf-8') dan Anda mendapatkan string dengan bagian dalam '\ u <someNumber>', yang dapat dicetak dengan sempurna.

Kemudian, sekali lagi - Anda ingin melakukan yang sebaliknya - membaca string yang disandikan dalam UTF-8 dan memperlakukannya sebagai Unicode, sehingga \ u360 akan menjadi satu karakter, bukan 5. Kemudian Anda mendekodekan string (dengan pengkodean yang dipilih) dan dapatkan objek baru dari jenis unicode.

Sama seperti catatan tambahan - Anda dapat memilih beberapa pengkodean cabul, seperti 'zip', 'base64', 'busuk' dan beberapa dari mereka akan dikonversi dari string ke string, tetapi saya percaya kasus yang paling umum adalah yang melibatkan UTF-8 / UTF-16 dan string.

Abgan
sumber
12

mybytestring.encode (somecodec) bermakna untuk nilai-nilai ini somecodec:

  • base64
  • bz2
  • zlib
  • hex
  • quopri
  • rot13
  • string_escape
  • kamu

Saya tidak yakin apa yang baik untuk decoding teks unicode diterjemahkan. Mencoba itu dengan penyandian apa pun tampaknya selalu mencoba untuk menyandikan dengan penyandian default sistem terlebih dahulu.

nosklo
sumber
5

Ada beberapa pengkodean yang dapat digunakan untuk mende / encode dari str ke str atau dari unicode ke unicode. Misalnya base64, hex atau bahkan rot13. Mereka terdaftar dalam modul codec .

Edit:

Pesan dekode pada string unicode dapat membatalkan operasi penyandian yang sesuai:

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

Jenis yang dikembalikan adalah str bukan unicode yang sangat disayangkan menurut saya. Tetapi ketika Anda tidak melakukan en- / decode yang tepat antara str dan unicode ini sepertinya berantakan.


sumber
1
-1: Metode decode tidak diterapkan ke objek unicode. Sebaliknya, objek unicode sedang dikodekan sebagai bytestring 'ascii', sebelum operasi decode dimulai. Untuk bukti pernyataan itu, coba u'ã'.decode ('hex') - yang menghasilkan UnicodeEncodeError
nosklo
2
@nosklo: Anda benar. Yang saya maksudkan adalah objek unicode memiliki metode decode () sehingga Anda dapat menerapkan codec non-karakter-encoding juga. Seluruh bisnis non-karakter-encoding ini membuat antarmuka ini berantakan dengan Python <3. #
1

Jawaban sederhana adalah bahwa mereka adalah kebalikan dari satu sama lain.

Komputer menggunakan unit byte yang sangat mendasar untuk menyimpan dan memproses informasi; itu tidak ada artinya bagi mata manusia.

Misalnya, '\ xe4 \ xb8 \ xad \ xe6 \ x96 \ x87' adalah representasi dari dua karakter bahasa Mandarin, tetapi komputer hanya tahu (artinya mencetak atau menyimpan) itu adalah Karakter Cina ketika mereka diberikan kamus untuk mencari yang Kata Cina, dalam hal ini, ini adalah kamus "utf-8", dan akan gagal menunjukkan kata Cina yang dimaksud dengan benar jika Anda melihat kamus yang berbeda atau salah (menggunakan metode pengodean kata yang berbeda).

Dalam kasus di atas, proses komputer untuk mencari kata dalam bahasa Cina adalah decode().

Dan proses penulisan komputer orang Cina ke dalam memori komputer adalah encode().

Jadi informasi yang disandikan adalah byte mentah, dan informasi yang di-decode adalah byte mentah dan nama kamus untuk referensi (tetapi bukan kamus itu sendiri).

Teluk Eren
sumber