Как избежать Python UnicodeDecodeError в фильтре Джинджи nl2br - PullRequest
6 голосов
/ 25 февраля 2011

Я использую фильтр nl2br от Jinja2, который выглядит следующим образом:

import re
from jinja2 import environmentfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
                      for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

Проблема в том, что «значение» имеет что-то кроме символов ascii (например: «/ mɒnˈtænə /» приводит к сбою),Я получаю эту ошибку:

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/app.py", line 889, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/app.py", line 879, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/app.py", line 876, in wsgi_app
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/app.py", line 695, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/mcrittenden/Dropbox/Code/dropdo/dropdo.py", line 105, in view
    return render_template(template, src = url, data = content)
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/templating.py", line 85, in render_template
    context, ctx.app)
  File "/usr/local/lib/python2.6/dist-packages/Flask-0.6.1-py2.6.egg/flask/templating.py", line 69, in _render
    rv = template.render(context)
  File "/usr/local/lib/python2.6/dist-packages/Jinja2-2.5.5-py2.6.egg/jinja2/environment.py", line 891, in render
    return self.environment.handle_exception(exc_info, True)
  File "/home/mcrittenden/Dropbox/Code/dropdo/templates/text.html", line 1, in top-level template code
    {% extends "layout.html" %}
  File "/home/mcrittenden/Dropbox/Code/dropdo/templates/layout.html", line 25, in top-level template code
    {% block content %}{% endblock %}
  File "/home/mcrittenden/Dropbox/Code/dropdo/templates/text.html", line 8, in block "content"
    {{ data|nl2br }}
  File "/home/mcrittenden/Dropbox/Code/dropdo/dropdo.py", line 26, in nl2br
    for p in _paragraph_re.split(escape(value)))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc9 in position 12: ordinal not in range(128)

Как лучше всего предотвратить ошибку, но не удалить символы проблемы в целом?

Ответы [ 3 ]

13 голосов
/ 25 февраля 2011

Используйте unicode литералы везде.

«Юникод в Python, полностью демистифицирован»

6 голосов
/ 25 февраля 2011

Если в «value» есть что-то, кроме символов ascii, вы хотите, чтобы это было Unicode и ничего, кроме Unicode, во всем приложении, за исключением нескольких мест, где вы явно его кодируете или декодируете. Также передайте Unicode в свои шаблоны.

Если вы каким-либо образом получаете строку "/ mɒnˈtænə /", вы, вероятно, знаете ее кодировку; используй это: value = "/mɒnˈtænə/".decode(the_encoding).

Как вы узнаете кодировку? HTTP-запрос знает свою кодировку. Файл XML знает свою кодировку. Обычного текстового файла обычно нет; Вы должны знать его кодировку другими способами.

Обратите внимание, что UTF-8 не является Unicode , хотя это кодировка, которая может полностью представлять Unicode. Это все еще кодировка, и чтобы получить строку Python Unicode из нее, вам нужно .decode("utf-8") это.

0 голосов
/ 21 августа 2013

Попробуйте unidecode от http://pypi.python.org/pypi/Unidecode

>>> from unidecode  import unidecode
>>> m=u'My fianc\xe9 David'; print m; print unidecode(m)
My fiancé David
My fiance David
>>> 
...