如何让这个Python2.6函数支持Unicode?
我有一个函数,是我从网上的NLTK书第一章修改过来的。这个函数对我很有帮助,但尽管我读过关于Unicode的章节,我还是觉得很困惑。
def openbookreturnvocab(book):
fileopen = open(book)
rawness = fileopen.read()
tokens = nltk.wordpunct_tokenize(rawness)
nltktext = nltk.Text(tokens)
nltkwords = [w.lower() for w in nltktext]
nltkvocab = sorted(set(nltkwords))
return nltkvocab
前几天我在《查拉图斯特拉如是说》上试了一下,结果把带有变音符号的字母o和u搞乱了。我相信你们中的一些人知道这是为什么。我也确信这很容易解决。我知道这和调用一个将词语重新编码为unicode字符串的函数有关。如果真是这样,那我觉得问题可能不在那个函数定义里,而是在我准备写入文件的地方:
def jotindex(jotted, filename, readmethod):
filemydata = open(filename, readmethod)
jottedf = '\n'.join(jotted)
filemydata.write(jottedf)
filemydata.close()
return 0
我听说我需要在从文件读取字符串后将其编码为unicode。我试着这样修改函数:
def openbookreturnvocab(book):
fileopen = open(book)
rawness = fileopen.read()
unirawness = rawness.decode('utf-8')
tokens = nltk.wordpunct_tokenize(unirawness)
nltktext = nltk.Text(tokens)
nltkwords = [w.lower() for w in nltktext]
nltkvocab = sorted(set(nltkwords))
return nltkvocab
但是当我在匈牙利语上使用它时出现了这个错误。而在德语上使用时没有错误。
>>> import bookroutines
>>> elles1 = bookroutines.openbookreturnvocab("lk1-les1")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bookroutines.py", line 9, in openbookreturnvocab
nltktext = nltk.Text(tokens)
File "/usr/lib/pymodules/python2.6/nltk/text.py", line 285, in __init__
self.name = " ".join(map(str, tokens[:8])) + "..."
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 4: ordinal not in range(128)
我这样修复了存储数据的函数:
def jotindex(jotted, filename, readmethod):
filemydata = open(filename, readmethod)
jottedf = u'\n'.join(jotted)
filemydata.write(jottedf)
filemydata.close()
return 0
然而,当我尝试存储德语时又出现了这个错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bookroutines.py", line 23, in jotindex
filemydata.write(jottedf)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 414: ordinal not in range(128)
>>>
...这就是你尝试写入u'\n'.join的数据时得到的结果。
>>> jottedf = u'/n'.join(elles1)
>>> filemydata.write(jottedf)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 504: ordinal not in range(128)
1 个回答
4
对于你从文件中读取的每个字符串,如果它们是UTF-8格式的,你可以通过调用 rawness.decode('utf-8')
来把它们转换成unicode格式。这样你就会得到unicode对象。另外,我不太清楚“jotted”是什么,但你可能需要确保它是一个unicode对象,然后用 u'\n'.join(jotted)
来处理。
更新:
看起来NLTK库对unicode对象不太友好。那么你需要确保使用的是UTF-8编码的字符串实例。试试这个:
tokens = nltk.wordpunct_tokenize(unirawness)
nltktext = nltk.Text([token.encode('utf-8') for token in tokens])
还有这个:
jottedf = u'\n'.join(jotted)
filemydata.write(jottedf.encode('utf-8'))
不过如果jotted真的只是一个UTF-8编码的字符串列表,那你就不需要这些,直接用这个就可以了:
jottedf = '\n'.join(jotted)
filemydata.write(jottedf)
顺便说一下,NLTK在处理unicode和编码方面似乎不太谨慎(至少在演示中是这样)。所以最好小心点,检查一下它是否正确处理了你的数据。此外,这可能是你在处理匈牙利文本时出现错误,而在处理德语文本时没有错误的原因,检查你的编码。