UnicodeDecodeError: кодек ascii не может декодировать байт 0x96 в позиции 10: порядковый номер не в диапазоне (128)

Как я могу получить данные из базы данных MySQL в кодировке UTF-8, не получая UnicodeDecodeError? Я делаю веб-сайт с использованием шаблонов Python и HTML. Вот код, который я использовал для получения данных из базы данных, который, казалось, работал нормально, пока я не переключил кодировку базы данных на UTF-8:

@app.route("/songs")
def content_database_song():
  c = connect_db()
  c.execute("
  SELECT * FROM Tracks
  JOIN Artists USING (ArtistID)
  JOIN Albums USING (AlbumID)
  JOIN Songs USING (SongID)
  ORDER BY UPPER(SoName), UPPER(AlTitle)
  ")
  songslist = []
  rows = c.fetchall()
  for row in rows:
    songslist.append(row)
  return render_template("/song-index.html", songslist = songslist)

Вот полная трассировка:

UnicodeDecodeError
UnicodeDecodeError: 'ascii' codec can't decode byte 0x96 in position 10: ordinal not in range(128)

Traceback (последний последний звонок)

File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1306, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1294, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1292, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1062, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1060, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/app.py", line 1047, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/samuelbradshaw/Sites/praises/index.py", line 59, in content_database_song
return render_template("/song-index.html", songslist = songslist)
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/templating.py", line 121, in render_template
context, ctx.app)
File "/Library/Python/2.7/site-packages/Flask-0.7.2-py2.7.egg/flask/templating.py", line 105, in _render
rv = template.render(context)
File "/Library/Python/2.7/site-packages/Jinja2-2.6-py2.7.egg/jinja2/environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "/Users/samuelbradshaw/Sites/praises/templates/song-index.html", line 1, in top-level template code
{% extends "database-nav.html" %}
File "/Users/samuelbradshaw/Sites/praises/templates/database-nav.html", line 1, in top-level template code
{% extends "layout.html" %}
File "/Users/samuelbradshaw/Sites/praises/templates/layout.html", line 26, in top-level template code
{% block content %}{% endblock %}
File "/Users/samuelbradshaw/Sites/praises/templates/database-nav.html", line 13, in block "content"
{% block subcontent %}
File "/Users/samuelbradshaw/Sites/praises/templates/song-index.html", line 47, in block "subcontent"
<strong>Related Scriptures:</strong> {% if song.SoRelatedScriptures != "" %}{{song.SoRelatedScriptures}}{% else %}None{% endif %}<br>
File "/Library/Python/2.7/site-packages/Jinja2-2.6-py2.7.egg/jinja2/_markupsafe/_native.py", line 21, in escape
return Markup(unicode(s)
UnicodeDecodeError: 'ascii' codec can't decode byte 0x96 in position 10: ordinal not in range(128)

person Samuel Bradshaw    schedule 22.04.2012    source источник
comment
Выложите всю трассировку, пожалуйста. Это, по крайней мере, даст нам некоторое представление, откуда вы получаете эту ошибку.   -  person kindall    schedule 22.04.2012
comment
Я предполагаю, что вам следует вернуться с UTF-8. Посмотрите здесь: stackoverflow .com/questions/7873556/   -  person paulsm4    schedule 22.04.2012
comment
Если первый байт, на который жалуется guff.decode('ascii'), равен 0x96, то guff не закодирован в UTF-8 — 0x96 НЕ является допустимым начальным байтом UTF-8. Я бы предложил вставить print repr(row) внутрь этого цикла for, чтобы мы могли точно видеть, что у вас есть, а не гадать. В какой кодировке была база данных до того, как вы переключили ее на UTF-8? Вы перезагрузили все свои текстовые данные после переключения?   -  person John Machin    schedule 22.04.2012
comment
Это был latin1, прежде чем я переключил его на UTF-8. Мне пришлось переключить его, потому что он не позволял мне ставить определенные знаки препинания (например, фигурные одинарные кавычки и тире).   -  person Samuel Bradshaw    schedule 22.04.2012
comment
Вы должны не только переключить, но и преобразовать базу данных в UTF-8. Я обычно делал бэкап, экспортировал в sql, создавал новый в UTF-8, импортировал, переименовывал и новый и старый, проверял какое-то время, удалял старый.   -  person hynekcer    schedule 22.04.2012
comment
Я ввел print repr(row), и он напечатал мою таблицу. Все n-тире отображаются как \x96, а фигурные апострофы — как \x92. Я предполагаю, что все, что мне нужно, это простое выражение decode, но я никогда не использовал его и не знаю, куда его поместить:) т.е. я помещаю его в свой шаблон, или я помещаю его в цикл for, или в заявлении return?   -  person Samuel Bradshaw    schedule 23.04.2012


Ответы (1)


Мне просто нужно было изменить одну часть кода — она была в методе connect_db(), на который есть ссылка во фрагменте кода, опубликованном выше. Я изменил это:

def connect_db():
  global conn
  conn = mdb.connect(dbinfo.server, dbinfo.username, dbinfo.password, dbinfo.database)
  return conn.cursor(mdb.cursors.DictCursor)

к этому:

def connect_db():
  global conn
  conn = mdb.connect(dbinfo.server, dbinfo.username, dbinfo.password, dbinfo.database, charset='utf8', use_unicode=True)
  return conn.cursor(mdb.cursors.DictCursor)

Обратите внимание на charset='utf8', use_unicode=True при подключении. Это все, что мне пришлось изменить после переключения моей базы данных на Unicode! :)

person Samuel Bradshaw    schedule 29.04.2012