如何在Python中解码ASCII

5

我使用postman发送包含西里尔字母的参数到django的url中,并获得了类似于%D0%B7%D0%B2这样的变量search_text

实际上,如果打印search_text,我会得到类似于текст的输出

我在控制台尝试了以下内容,并且没有出现错误

>>> a = "текст"
>>> a
'\xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82'
>>> print a
текст
>>> b = a.decode("utf-8")
>>> b
u'\u0442\u0435\u043a\u0441\u0442'
>>> print b
текст
>>>

如果没有控制台,我会遇到错误:

"""WHERE title LIKE '%%{}%%' limit '{}';""".format(search_text, limit))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

如何预防它?


你在使用Python 2吗? - Nikita
请查看我的更新答案。 - Nikita
3个回答

3

要解码带有“%”符号的url编码字符串,请使用 urllib

import urllib
byte_string=urllib.unquote('%D0%B7%D0%B2')

然后您需要对byte_string进行解码,将其转换为原始编码格式,例如:

import urllib
import codecs
byte_string=urllib.unquote('%D0%B7%D0%B2')
unicode_string=codecs.decode(byte_string, 'utf-8')

print(unicode_string) 将会打印出 зв

问题出在未知的编码上。你需要知道获取到的数据使用的是哪种编码方式。要指定.py文件中使用的默认编码,可以在文件顶部添加以下代码:

# -*- coding: utf-8 -*-

西里尔字母可能是'cp866'、'cp1251'、'koi8_r'和'utf-8',这些是最常见的。所以在使用decode时,请尝试这些编码。

Python 2默认不使用Unicode,因此最好启用它或切换到Python 3。要在.py文件中启用Unicode,请在所有导入语句之前添加以下行:

from __future__ import unicode_literals

例如,在Python 2.7.9中,以下代码可以正常工作:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

a="текст"
c="""WHERE title LIKE '%%{}%%' limit '{}';""".format(a, '10')
print(c)

另请参见:

https://docs.python.org/2/library/codecs.html

https://docs.python.org/2/howto/unicode.html


这很有帮助,谢谢。但我仍然有一个问题,当我使用unicode_literals并尝试使用like %search_text%进行查询时,此查询在某种程度上是区分大小写的,并且Звзв之间存在差异。我尝试了使用LOWER(title)UPPER(title)LOWER(search_text)的SQL语句,但没有帮助。也许您对此有任何想法?如何进行西里尔文不区分大小写选择。 - Roberto
@Roberto:这取决于数据库。可能更好的做法是提出一个单独的问题(也许已经存在)。 - RemcoGerlich
@Roberto,这与unicode_literals无关。unicode_literals只是让Python 2中的字符串表现得像Python 3一样,默认情况下使所有字符串成为Unicode。大小写敏感性是特定于数据库的,您可能只想使用ILIKE而不是LIKE,后者是不区分大小写的。 - Nikita

2

这取决于 Django 程序所期望的编码方式以及字符串 search_text, limit 的编码方式。通常,只需要这样做:

"""WHERE title LIKE '%%{}%%' limit '{}';""".decode("utf-8").format(search_text.decode("utf-8"), limit)

编辑** 在阅读您的编辑后,似乎您在将URL解析的文本更改回字符串时遇到了问题。以下是如何执行此操作的示例:

import urlparse
print urlparse.urlunparse(urlparse.urlparse("ресторан"))

这也会返回一个错误:UnicodeEncodeError: 'ascii'编解码器无法对位置0-1的字符进行编码:超出范围(128) - Roberto
你需要更清楚地说明search_text、limit以及Django所需的编码方式。请再试一次,我已经编辑了代码。 - bmbigbang
同样的错误:return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii'编解码器无法对0-1位置的字符进行编码:该编号不在128范围内 - Roberto
那是因为你还需要解码你正在格式化的字符串。我再次更改代码,请确保“limit”中没有任何非ASCII字符。 - bmbigbang
仍然出现相同的错误,我也尝试在控制台中执行,但没有出错。我还更新了描述。 - Roberto
将Unicode转换为正确的URL,您可以尝试使用以下方法: https://dev59.com/4nRA5IYBdhLWcg3w2xsI - bmbigbang

1

您的建议对我无效,并返回以下错误:UnicodeDecodeError:'ascii' codec can't decode byte 0xd0 in position 23: ordinal not in range(128)。 - Roberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接