我试图在UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-51: ordinal not in range(128)
中使用string.maketrans
时遇到Python
异常。我对以下代码(gist)中的这种错误感到气馁:
# -*- coding: utf-8 -*-
import string
def translit1(string):
""" This function works just fine """
capital_letters = {
u'А': u'A',
u'Б': u'B',
u'В': u'V',
u'Г': u'G',
u'Д': u'D',
u'Е': u'E',
u'Ё': u'E',
u'Ж': u'Zh',
u'З': u'Z',
u'И': u'I',
u'Й': u'Y',
u'К': u'K',
u'Л': u'L',
u'М': u'M',
u'Н': u'N',
u'О': u'O',
u'П': u'P',
u'Р': u'R',
u'С': u'S',
u'Т': u'T',
u'У': u'U',
u'Ф': u'F',
u'Х': u'H',
u'Ц': u'Ts',
u'Ч': u'Ch',
u'Ш': u'Sh',
u'Щ': u'Sch',
u'Ъ': u'',
u'Ы': u'Y',
u'Ь': u'',
u'Э': u'E',
u'Ю': u'Yu',
u'Я': u'Ya'
}
lower_case_letters = {
u'а': u'a',
u'б': u'b',
u'в': u'v',
u'г': u'g',
u'д': u'd',
u'е': u'e',
u'ё': u'e',
u'ж': u'zh',
u'з': u'z',
u'и': u'i',
u'й': u'y',
u'к': u'k',
u'л': u'l',
u'м': u'm',
u'н': u'n',
u'о': u'o',
u'п': u'p',
u'р': u'r',
u'с': u's',
u'т': u't',
u'у': u'u',
u'ф': u'f',
u'х': u'h',
u'ц': u'ts',
u'ч': u'ch',
u'ш': u'sh',
u'щ': u'sch',
u'ъ': u'',
u'ы': u'y',
u'ь': u'',
u'э': u'e',
u'ю': u'yu',
u'я': u'ya'
}
translit_string = ""
for index, char in enumerate(string):
if char in lower_case_letters.keys():
char = lower_case_letters[char]
elif char in capital_letters.keys():
char = capital_letters[char]
if len(string) > index+1:
if string[index+1] not in lower_case_letters.keys():
char = char.upper()
else:
char = char.upper()
translit_string += char
return translit_string
def translit2(text):
""" This method should be more easy to grasp,
but throws exception:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-51: ordinal not in range(128)
"""
symbols = string.maketrans(u"абвгдеёзийклмнопрстуфхъыьэАБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЬЭ",
u"abvgdeezijklmnoprstufh'y'eABVGDEEZIJKLMNOPRSTUFH'Y'E")
sequence = {
u'ж':'zh',
u'ц':'ts',
u'ч':'ch',
u'ш':'sh',
u'щ':'sch',
u'ю':'ju',
u'я':'ja',
u'Ж':'Zh',
u'Ц':'Ts',
u'Ч':'Ch'
}
for char in sequence.keys():
text = text.replace(char, sequence[char])
return text.translate(symbols)
if __name__ == "__main__":
print translit1(u"Привет") # prints Privet as expected
print translit2(u"Привет") # throws exception: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-51: ordinal not in range(128)
原始痕迹:
Traceback (most recent call last):
File "translit_error.py", line 124, in <module>
print translit2(u"Привет") # throws exception: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-51: ordinal not in range(128)
File "translit_error.py", line 103, in translit2
u"abvgdeezijklmnoprstufh'y'eABVGDEEZIJKLMNOPRSTUFH'Y'E")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-51: ordinal not in range(128)
我的意思是,为什么Python string.maketrans
试图使用ascii
表呢?为什么英文字母超出0-128范围?
$ python -c "print ord(u'A')"
65
$ python -c "print ord(u'z')"
122
$ python -c "print ord(u\"'\")"
39
几个小时后,我觉得自己已经筋疲力尽了解决这个问题。
有人能说出发生了什么以及如何解决这个问题吗?
答案 0 :(得分:19)
您可以使用音译包(https://pypi.python.org/pypi/transliterate)
示例#1:
from transliterate import translit
print translit("Lorem ipsum dolor sit amet", "ru")
# Лорем ипсум долор сит амет
示例#2:
print translit(u"Лорем ипсум долор сит амет", "ru", reversed=True)
# Lorem ipsum dolor sit amet
答案 1 :(得分:17)
translate的行为会有所不同。您必须提供字典maketrans
:
ord(search)->ord(replace)
表
symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
u"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA")
tr = {ord(a):ord(b) for a, b in zip(*symbols)}
# for Python 2.*:
# tr = dict( [ (ord(a), ord(b)) for (a, b) in zip(*symbols) ] )
text = u'Добрый Ден'
print text.translate(tr) # looks good
那就是说,我建议不要重新发明轮子并使用已建立的图书馆:http://pypi.python.org/pypi/Unidecode
答案 2 :(得分:4)
查看CyrTranslit包,它专门用于音译西里尔语脚本文本。它目前支持塞尔维亚语,黑山语,马其顿语和俄语。
使用示例:
>>> import cyrtranslit
>>> cyrtranslit.supported()
['me', 'sr', 'mk', 'ru']
>>> cyrtranslit.to_latin('Моё судно на воздушной подушке полно угрей', 'ru')
'Moyo sudno na vozdushnoj podushke polno ugrej'
>>> cyrtranslit.to_cyrillic('Moyo sudno na vozdushnoj podushke polno ugrej')
'Моё судно на воздушной подушке полно угрей'
答案 3 :(得分:1)
这是另一个具有更准确音译的简短解决方案:
symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ ",
(*list(u'abvgdee'), 'zh', *list(u'zijklmnoprstuf'), 'kh', 'z', 'ch', 'sh', 'sh', '',
'y', '', 'e', 'yu','ya', *list(u'ABVGDEE'), 'ZH',
*list(u'ZIJKLMNOPRSTUF'), 'KH', 'Z', 'CH', 'SH', 'SH', *list(u'_Y_E'), 'YU', 'YA', ' '))
coding_dict = {source: dest for source, dest in zip(*symbols)}
translate = lambda x: ''.join([coding_dict[i] for i in x])
text = u'Добро пожаловать'
translate(text)
# 'Dobro pozhalovat'