Как я могу заставить эту функцию Python2.6 работать с Unicode? - PullRequest
0 голосов
/ 22 сентября 2010

У меня есть эта функция, которую я изменил из материала в главе 1 онлайн-книги NLTK. Это было очень полезно для меня, но, несмотря на чтение главы о Юникоде, я чувствую себя таким же потерянным, как и раньше.

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

Когда я попробовал это на днях в «Также Спрах Заратустра», слова были помяты с умлатой над «о» и «у». Я уверен, что некоторые из вас будут знать, почему это произошло. Я также уверен, что это довольно легко исправить. Я знаю, что это просто связано с вызовом функции, которая перекодирует токены в строки Unicode. Если это так, то, как мне кажется, это вообще может не произойти внутри определения этой функции, но здесь, где я готовлюсь записать в файл:

def jotindex(jotted, filename, readmethod):
    filemydata = open(filename, readmethod)
    jottedf = '\n'.join(jotted)
    filemydata.write(jottedf)
    filemydata.close()
    return 0

Я слышал, что мне нужно было закодировать строку в юникод после чтения из файла. Я попытался изменить функцию следующим образом:

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'ed данные.

>>> 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 голосов
/ 22 сентября 2010

Для каждой строки, которую вы читаете из своего файла, вы можете преобразовать их в Unicode, вызвав rawness.decode('utf-8'), если у вас есть текст в UTF-8. Вы будете в конечном итоге с объектами Unicode. Кроме того, я не знаю, что такое "jotted", но вы можете убедиться, что это объект Unicode, и использовать вместо него u'\n'.join(jotted).

Обновление:

Похоже, что библиотека NLTK не любит объекты Unicode. Хорошо, тогда вы должны убедиться, что вы используете экземпляры str с текстом в кодировке 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 не очень осторожен в отношении юникода и кодирования (по крайней мере, демонстраций). Лучше быть осторожным и проверить, правильно ли он обработал ваши токены. Кроме того, и это могло быть причиной того, что вы получаете ошибки с венгерским текстом, а не немецким текстом, проверьте ваши кодировки .

...