I'm trying to print the following unicode string but I'm receiving a UnicodeDecodeError: 'ascii' codec can't decode byte
error. Can you please help form this query so it can print the unicode string properly?
>>> from __future__ import unicode_literals
>>> ts='now'
>>> free_form_request='[EXID(이엑스아이디)] 위아래 (UP&DOWN) MV'
>>> nick='me'>>> print('{ts}: free form request {free_form_request} requested from {nick}'.format(ts=ts,free_form_request=free_form_request.encode('utf-8'),nick=nick))Traceback (most recent call last):File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xec in position 6: ordinal not in range(128)
Thank you very much in advance!
Here's what happen when you construct this string:
'{ts}: free form request {free_form_request} requested from {nick}'.format(ts=ts,free_form_request=free_form_request.encode('utf-8'),nick=nick)
free_form_request
is encode
-d into a byte string using utf-8
as the encoding. This works because utf-8
can represent [EXID(이엑스아이디)] 위아래 (UP&DOWN) MV
.
- However, the format string (
'{ts}: free form request {free_form_request} requested from {nick}'
) is a unicode string (because of imported from __future__ import unicode_literals
).
- You can't use byte strings as format arguments for a unicode string, so Python attempts to
decode
the byte string created in 1. to create a unicode string (which would be valid as an format argument).
- Python attempts the
decode
-ing using the default encoding, which is ascii
, and fails, because the byte string is a utf-8
byte string that includes byte values that don't make sense in ascii
.
- Python throws a
UnicodeDecodeError
.
Note that while the code is obviously doing something here, this would actually not throw an exception on Python 3, which would instead substitute the repr
of the byte string (the repr
being a unicode string).
To fix your issue, just pass unicode strings to format
.
That is, don't do step 1. where you encoded free_form_request
as a byte string: keep it as a unicode string by removing .encode(...)
:
'{ts}: free form request {free_form_request} requested from {nick}'.format(ts=ts, free_form_request=free_form_request, nick=nick)
Note Padraic Cunningham's answer in the comments as well.