Як виправити: "UnicodeDecodeError: кодек ascii не може декодувати байт";

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

Як це виправити?

У деяких інших статичних додатках для ведення блогу на основі python китайський пост може бути успішно опублікований. Наприклад, у цьому додатку: http://github.com/vrypan/bucket3. На моєму сайті http://bc3.brite.biz/ китайський пост успішно публікується.

**Нарешті я зрозумів.

as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

**Дозвольте мені перевірити.

as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec  6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)

>>> sys.getdefaultencoding()
'utf8'
>>>

Вище показано, що за замовчуванням у python використовується кодування utf8. Тоді помилки більше немає.

Коментарі (14)

Це класична "проблема юнікоду". Я вважаю, що пояснення цього виходить за рамки відповіді на StackOverflow, щоб повністю пояснити, що відбувається.

Це добре пояснюється тут.

Якщо дуже коротко, то ви передали щось, що інтерпретується як рядок байтів, чомусь, що має декодувати його в символи Unicode, але стандартний кодек (ascii) дає збій.

Презентація, на яку я вказав вам, містить поради, як цього уникнути. Зробіть свій код "юнікод-сендвічем". У Python 2 допомагає використання from __future__ import unicode_literals.

Оновлення: як можна виправити код:

Гаразд - у вашій змінній "source" є якісь байти. З вашого питання не зрозуміло, як вони туди потрапили - можливо, ви їх зчитали з веб-форми? У будь-якому випадку, вони не закодовані ascii, але python намагається перекодувати їх в юнікод, припускаючи, що це так. Вам потрібно явно вказати йому кодування. Це означає, що вам потрібно знати яке це кодування! Це не завжди легко, і це повністю залежить від того, звідки прийшов цей рядок. Ви можете поекспериментувати з деякими поширеними кодуваннями - наприклад, UTF-8. Ви повідомляєте unicode() кодування як другий параметр:

source = unicode(source, 'utf-8')
Коментарі (11)

У деяких випадках, коли ви перевіряєте кодування за замовчуванням (print sys.getdefaultencoding()), він повертає, що ви використовуєте ASCII. Якщо змінити на UTF-8, то це не спрацьовує, в залежності від вмісту змінної. Я знайшов інший спосіб:

import sys
reload(sys)  
sys.setdefaultencoding('Cp1252')
Коментарі (4)