在Python中处理古怪的编码

在Python中处理古怪的编码,python,unicode,encoding,character-encoding,Python,Unicode,Encoding,Character Encoding,我有一个Python脚本,它可以从许多源(数据库、文件等)提取数据。假设所有字符串都是unicode,但我最终得到的是以下主题的任何变化(由repr()返回): 是否有可靠的方法获取上述任意四个字符串并返回正确的unicode字符串 u'D\xe9cor' # --> Décor 我现在唯一能想到的方法是使用eval(),replace(),以及一种永远不会消失的深深的、灼热的羞耻感。这就是。用于将其转换为unicode >>> 'D\xc3\xa9cor'.decod

我有一个Python脚本,它可以从许多源(数据库、文件等)提取数据。假设所有字符串都是unicode,但我最终得到的是以下主题的任何变化(由
repr()
返回):

是否有可靠的方法获取上述任意四个字符串并返回正确的unicode字符串

u'D\xe9cor' # --> Décor
我现在唯一能想到的方法是使用
eval()
replace()
,以及一种永远不会消失的深深的、灼热的羞耻感。

这就是。用于将其转换为
unicode

>>> 'D\xc3\xa9cor'.decode('utf-8')
u'D\xe9cor'
您可以对
'D\\xc3\\xa9cor'
案例执行额外的字符串转义解码

>>> 'D\xc3\xa9cor'.decode('string-escape').decode('utf-8')
u'D\xe9cor'
>>> 'D\\xc3\\xa9cor'.decode('string-escape').decode('utf-8')
u'D\xe9cor'
>>> u'D\\xc3\\xa9cor'.decode('string-escape').decode('utf-8')
u'D\xe9cor'
为了处理第二种情况,您需要检测输入是否为
unicode
,并首先将其转换为
str

>>> def conv(s):
...   if isinstance(s, unicode):
...     s = s.encode('iso-8859-1')
...   return s.decode('string-escape').decode('utf-8')
... 
>>> map(conv, [u'D\\xc3\\xa9cor', u'D\xc3\xa9cor', 'D\\xc3\\xa9cor', 'D\xc3\xa9cor'])
[u'D\xe9cor', u'D\xe9cor', u'D\xe9cor', u'D\xe9cor']

编写适配器,了解哪些转换应应用于其源

>>> 'D\xc3\xa9cor'.decode('utf-8')
u'D\xe9cor'
>>> 'D\\xc3\\xa9cor'.decode('string-escape').decode('utf-8')
u'D\xe9cor'

这是我在看到肯尼特正确、更简洁的解决方案之前想到的解决方案:

def ensure_unicode(string):
    try:
        string = string.decode('string-escape').decode('string-escape')
    except UnicodeEncodeError:
        string = string.encode('raw_unicode_escape')

    return unicode(string, 'utf-8')

它适用于那个特殊情况。但是:u'D\\xc3\\xa9cor'-->u'D\\xc3\\xa9cor',u'D\xc3\xa9cor'-->UnicodeEncodeError,'D\\xc3\\xa9cor'-->u'D\\xc3\\xa9cor',@Tyson:它不能适用于所有情况。如何确保
'D:\\xc3\\xa9\\xc3xa9.png'
确实是一个UTF-8编码的字符串,而不是Windows路径名?我可以假设我收到的数据中没有一个是Windows路径名。@Tyson:在注释中你说的
UnicodeEncodeError
。请注意,它是编码,而不是解码。出于好奇:你是在一个循环中(在控制台或窗口中)打印出来的吗?这只是一个星期一早上的猜测……对于调试,是的,我把它扔给了
stdout
。没有古怪的编码,只有古怪的程序员。
def ensure_unicode(string):
    try:
        string = string.decode('string-escape').decode('string-escape')
    except UnicodeEncodeError:
        string = string.encode('raw_unicode_escape')

    return unicode(string, 'utf-8')