185

I've never been sure that I understand the difference between str/unicode decode and encode.

I know that str().decode() is for when you have a string of bytes that you know has a certain character encoding, given that encoding name it will return a unicode string.

I know that unicode().encode() converts unicode chars into a string of bytes according to a given encoding name.

But I don't understand what str().encode() and unicode().decode() are for. Can anyone explain, and possibly also correct anything else I've gotten wrong above?

EDIT:

Several answers give info on what .encode does on a string, but no-one seems to know what .decode does for unicode.

cedbeu
  • 1,919
  • 14
  • 24
ʞɔıu
  • 47,148
  • 35
  • 106
  • 149
  • I think the second answer of [this page](http://stackoverflow.com/questions/10288016/usage-of-unicode-and-encode-functions-in-python) is clear enough and concise. – Ben Dec 01 '16 at 11:24

7 Answers7

106

The decode method of unicode strings really doesn't have any applications at all (unless you have some non-text data in a unicode string for some reason -- see below). It is mainly there for historical reasons, i think. In Python 3 it is completely gone.

unicode().decode() will perform an implicit encoding of s using the default (ascii) codec. Verify this like so:

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

The error messages are exactly the same.

For str().encode() it's the other way around -- it attempts an implicit decoding of s with the default encoding:

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

Used like this, str().encode() is also superfluous.

But there is another application of the latter method that is useful: there are encodings that have nothing to do with character sets, and thus can be applied to 8-bit strings in a meaningful way:

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

You are right, though: the ambiguous usage of "encoding" for both these applications is... awkard. Again, with separate byte and string types in Python 3, this is no longer an issue.

  • 4
    `.decode()` on Unicode strings might be useful e.g., `print u'\\u0203'.decode('unicode-escape')` – jfs Dec 21 '13 at 04:06
  • Good example @J.F.Sebastian in python3 I guess you would do: `print u'\\u0203'.encode('utf8').decode('unicode-escape')` – AJP Mar 27 '14 at 11:54
  • 1
    @AJP: on Python 3: `codecs.decode(u'\\u0203', 'unicode-escape')` – jfs Mar 27 '14 at 16:57
  • @hop: yes. To detect invalid input and for Python 2/3 compatibility, the string can be encoded explicitly using `ascii` encoding: `\\u0203\u00e4'.encode('ascii').decode('unicode-escape')` – jfs Jun 30 '15 at 18:39
  • @hop: your first comment (Why have you deleted it? Don't delete comments that have been replied to) already said it. My reply (`.encode('ascii').decode('unicode-escape')`) does not depend on `sys.getdefaultencoding()`. – jfs Jun 30 '15 at 19:02
71

To represent a unicode string as a string of bytes is known as encoding. Use u'...'.encode(encoding).

Example:

    >>> 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 can't encode characters in position 0-5: 
    ordinal not in range(128)

You typically encode a unicode string whenever you need to use it for IO, for instance transfer it over the network, or save it to a disk file.

To convert a string of bytes to a unicode string is known as decoding. Use unicode('...', encoding) or '...'.decode(encoding).

Example:

   >>> u'æøå'
   u'\xc3\xa6\xc3\xb8\xc3\xa5' # the interpreter prints the unicode object like so
   >>> 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'

You typically decode a string of bytes whenever you receive string data from the network or from a disk file.

I believe there are some changes in unicode handling in python 3, so the above is probably not correct for python 3.

Some good links:

codeape
  • 97,830
  • 24
  • 159
  • 188
  • 6
    You didn't answer the OP's question. OP wants to know what str.encode() and unicode.decode() do. You just repeated what was stated in the original question. – stuckintheshuck Sep 04 '13 at 17:20
  • Great answer for why in practice you'd ever mess with decoding and encoding. Not every machine understands the same set of characters, but they all understand bytes. Encode into bytes for a language computers universally understand (and can be transferred or saved to disk), but decode when humans actually have to read those bytes (eg. at the client side). – Alex Petralia Jul 18 '17 at 15:16
  • Fantastic answer! This should go up!! – sandyp Oct 18 '18 at 16:29
16

anUnicode.encode('encoding') results in a string object and can be called on a unicode object

aString.decode('encoding') results in an unicode object and can be called on a string, encoded in given encoding.


Some more explanations:

You can create some unicode object, which doesn't have any encoding set. The way it is stored by Python in memory is none of your concern. You can search it, split it and call any string manipulating function you like.

But there comes a time, when you'd like to print your unicode object to console or into some text file. So you have to encode it (for example - in UTF-8), you call encode('utf-8') and you get a string with '\u<someNumber>' inside, which is perfectly printable.

Then, again - you'd like to do the opposite - read string encoded in UTF-8 and treat it as an Unicode, so the \u360 would be one character, not 5. Then you decode a string (with selected encoding) and get brand new object of the unicode type.

Just as a side note - you can select some pervert encoding, like 'zip', 'base64', 'rot' and some of them will convert from string to string, but I believe the most common case is one that involves UTF-8/UTF-16 and string.

Abgan
  • 3,696
  • 22
  • 31
12

mybytestring.encode(somecodec) is meaningful for these values of somecodec:

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

I am not sure what decoding an already decoded unicode text is good for. Trying that with any encoding seems to always try to encode with the system's default encoding first.

nosklo
  • 217,122
  • 57
  • 293
  • 297
5

There are a few encodings that can be used to de-/encode from str to str or from unicode to unicode. For example base64, hex or even rot13. They are listed in the codecs module.

Edit:

The decode message on a unicode string can undo the corresponding encode operation:

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

The returned type is str instead of unicode which is unfortunate in my opinion. But when you are not doing a proper en-/decode between str and unicode this looks like a mess anyway.

  • 1
    -1: The decode method is not being applied to the unicode object. Instead, the unicode object is being encoded as an 'ascii' bytestring, before decode operation starts. For a proof of that assertion, try u'ã'.decode('hex') - that yields UnicodeEncodeError – nosklo Jan 16 '09 at 11:17
  • 2
    @nosklo: You are right. What I really meant is that unicode objects have a decode() method so that you can apply non-character-encoding-codecs to them, too. This whole non-character-encoding-business makes this interface a mess in Python < 3. –  Jan 16 '09 at 19:43
1

The simple answer is that they are the exact opposite of each other.

The computer uses the very basic unit of byte to store and process information; it is meaningless for human eyes.

For example,'\xe4\xb8\xad\xe6\x96\x87' is the representation of two Chinese characters, but the computer only knows (meaning print or store) it is Chinese Characters when they are given a dictionary to look for that Chinese word, in this case, it is a "utf-8" dictionary, and it would fail to correctly show the intended Chinese word if you look into a different or wrong dictionary (using a different decoding method).

In the above case, the process for a computer to look for Chinese word is decode().

And the process of computer writing the Chinese into computer memory is encode().

So the encoded information is the raw bytes, and the decoded information is the raw bytes and the name of the dictionary to reference (but not the dictionary itself).

AnonymousAngelo
  • 996
  • 3
  • 15
  • 37
Eren Bay
  • 63
  • 6
0

Both are opposite to each other.

  1. Encoding is referred to as the sender creating a message in a certain format to make it readable by the receiver.

for example:

import base64
def read_csv_file():
 with open( r'File_Path.csv', 'r') as fb:
   csv_read = csv.DictReader(fb)
   for row in csv_read:
     id = row["EMP_ID"].encode("ascii")
     x = base64.b64encode(bytes(id))      #encode
     print(x)
read_csv_file()
  1. Decoding is referred to as the interpretation of the encoded message by the receiver.

    for example:

    print(base64.b64decode(b'SFExMTE='))