2015-03-04 3 views
3

Я пытаюсь сохранить конкретный контент словаря в файл, но когда я пытаюсь его написать, я получаю следующее сообщение об ошибке:UnicodeDecodeError: кодек ascii не может декодировать байт 0xc3 в позиции 40: порядковый номер не в диапазоне (128)

Traceback (most recent call last): 
    File "P4.py", line 83, in <module> 
    outfile.write(u"{}\t{}\n".format(keyword, str(tagSugerido)).encode("utf-8")) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 40: ordinal not in range(128) 

А вот код:

from collections import Counter 

with open("corpus.txt") as inf: 
    wordtagcount = Counter(line.decode("latin_1").rstrip() for line in inf) 

with open("lexic.txt", "w") as outf: 
    outf.write('Palabra\tTag\tApariciones\n'.encode("utf-8")) 
    for word,count in wordtagcount.iteritems(): 
     outf.write(u"{}\t{}\n".format(word, count).encode("utf-8")) 
""" 
2) TAGGING USING THE MODEL 
Dados los ficheros de test, para cada palabra, asignarle el tag mas 
probable segun el modelo. Guardar el resultado en ficheros que tengan 
este formato para cada linea: Palabra Prediccion 
""" 
file=open("lexic.txt", "r") # abrimos el fichero lexic (nuestro modelo) (probar con este) 
data=file.readlines() 
file.close() 
diccionario = {} 

""" 
In this portion of code we iterate the lines of the .txt document and we create a dictionary with a word as a key and a List as a value 
Key: word 
Value: List ([tag, #ocurrencesWithTheTag]) 
""" 
for linea in data: 
    aux = linea.decode('latin_1').encode('utf-8') 
    sintagma = aux.split('\t') # Here we separate the String in a list: [word, tag, ocurrences], word=sintagma[0], tag=sintagma[1], ocurrences=sintagma[2] 
    if (sintagma[0] != "Palabra" and sintagma[1] != "Tag"): #We are not interested in the first line of the file, this is the filter 
     if (diccionario.has_key(sintagma[0])): #Here we check if the word was included before in the dictionary 
      aux_list = diccionario.get(sintagma[0]) #We know the name already exists in the dic, so we create a List for every value 
      aux_list.append([sintagma[1], sintagma[2]]) #We add to the list the tag and th ocurrences for this concrete word 
      diccionario.update({sintagma[0]:aux_list}) #Update the value with the new list (new list = previous list + new appended element to the list) 
     else: #If in the dic do not exist the key, que add the values to the empty list (no need to append) 
      aux_list_else = ([sintagma[1],sintagma[2]]) 
      diccionario.update({sintagma[0]:aux_list_else}) 

""" 
Here we create a new dictionary based on the dictionary created before, in this new dictionary (diccionario2) we want to keep the next 
information: 
Key: word 
Value: List ([suggestedTag, #ocurrencesOfTheWordInTheDocument, probability]) 

For retrieve the information from diccionario, we have to keep in mind: 

In case we have more than 1 Tag associated to a word (keyword), we access to the first tag with keyword[0], and for ocurrencesWithTheTag with keyword[1], 
from the second case and forward, we access to the information by this way: 

diccionario.get(keyword)[2][0] -> with this we access to the second tag 
diccionario.get(keyword)[2][1] -> with this we access to the second ocurrencesWithTheTag 
diccionario.get(keyword)[3][0] -> with this we access to the third tag 
... 
.. 
. 
etc. 
""" 
diccionario2 = dict.fromkeys(diccionario.keys())#We create a dictionary with the keys from diccionario and we set all the values to None 
with open("estimation.txt", "w") as outfile: 
    for keyword in diccionario: 
     tagSugerido = unicode(diccionario.get(keyword[0]).decode('utf-8')) #tagSugerido is the tag with more ocurrences for a concrete keyword 
     maximo = float(diccionario.get(keyword)[1]) #maximo is a variable for the maximum number of ocurrences in a keyword 
     if ((len(diccionario.get(keyword))) > 2): #in case we have > 2 tags for a concrete word 
      suma = float(diccionario.get(keyword)[1]) 
      for i in range (2, len(diccionario.get(keyword))): 
       suma += float(diccionario.get(keyword)[i][1]) 
       if (diccionario.get(keyword)[i][1] > maximo): 
        tagSugerido = unicode(diccionario.get(keyword)[i][0]).decode('utf-8')) 
        maximo = float(diccionario.get(keyword)[i][1]) 
      probabilidad = float(maximo/suma); 
      diccionario2.update({keyword:([tagSugerido, suma, probabilidad])}) 

     else: 
      diccionario2.update({keyword:([diccionario.get(keyword)[0],diccionario.get(keyword)[1], 1])}) 

     outfile.write(u"{}\t{}\n".format(keyword, tagSugerido).encode("utf-8")) 

нужный выход будет выглядеть следующим образом:

keyword(String) tagSugerido(String): 
Hello NC 
Friend N 
Run  V 
...etc 

Конфликтная линия:

outfile.write(u"{}\t{}\n".format(keyword, str(tagSugerido)).encode("utf-8")) 

Спасибо.

ответ

2

Как вы не даете простой лаконичный код, чтобы проиллюстрировать ваш вопрос, я просто дам вам общие советы о том, что должно быть ошибка:

Если вы получаете сообщение об ошибке декодирования, то, что tagSugerido читается как ASCII, а не как Unicode. Чтобы исправить это, вы должны сделать:

tagSugerido = unicode(diccionario.get(keyword[0]).decode('utf-8')) 

хранить его как unicode.

Тогда вы, вероятно, получите сообщение об ошибке кодирования на write() этапе, и вы должны исправить ваши записи следующим образом:

outfile.write(u"{}\t{}\n".format(keyword, str(tagSugerido)).encode("utf-8")) 

должно быть:

outfile.write(u"{}\t{}\n".format(keyword, tagSugerido.encode("utf-8"))) 

Я litterally ответил очень похожий вопрос moments ago. И при работе с строками unicode, переключиться на python3, это сделает вашу жизнь проще!

Если вы не можете переключиться на Python3 только все же, вы можете сделать свой python2 вести себя, как это почти python3, используя оператор python-future импорта:

from __future__ import absolute_import, division, print_function, unicode_literals 

NB: вместо того, чтобы делать:

file=open("lexic.txt", "r") # abrimos el fichero lexic (nuestro modelo) (probar con este) 
data=file.readlines() 
file.close() 

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

with open("lexic.txt", "r") as f: 
    data=f.readlines() 

, который позаботится о том, чтобы всегда закрывать файл даже при сбое.

N.B.2: Избегайте использования файла, как это тип питон вы затенение, но использовать f или lexic_file ...

+0

Спасибо за вашу помощь, я обновил код с подсказками, но теперь я получаю эту ошибку: 'Файл«P4.py», строка 75 outfile.write (U" {} \ т {} \ n ".format (ключевое слово, tagSugerido.encode (" utf-8 ")))^ SyntaxError: недействительный синтаксис – Gera

+0

@Gerard не дает мне недействительный синтаксис. Может быть, у вас что-то не так на другой линии? –

+0

@gerard, пожалуйста, сделайте [SSCCE] (http://ssce.org), давая ошибку в комментарии (таким образом, когда невозможно узнать, какой символ указывает '^'), и код, который анализирует двух файлов, которые у нас нет, не помогает. Посмотрите на мой другой ответ, чтобы показать, как вы можете сделать ошибку в нескольких строках с несколькими файлами одной строки. – zmo

2

Как ZMO предложил:

outfile.write(u"{}\t{}\n".format(keyword, str(tagSugerido)).encode("utf-8")) 

должно быть:

outfile.write(u"{}\t{}\n".format(keyword, tagSugerido.encode("utf-8"))) 

Примечание по юникоду в Python 2

Ваше программное обеспечение должно o nly работать со строками unicode внутри, преобразовывая в конкретную кодировку на выходе.

ли предотвратить делает ту же ошибку снова и снова, вы должны убедиться, что вы поняли разницу между и ASCII UTF-8 кодировками, а также между ул и юникода объектов в Python.

Разница между ASCII и UTF-8 кодировке:

Ascii нуждается только один байт для представления всех возможных символов в ASCII-кодировки/кодирования. Для представления полной кодировки UTF-8 требуется до четырех байтов.

ascii (default) 
1 If the code point is < 128, each byte is the same as the value of the code point. 
2 If the code point is 128 or greater, the Unicode string can’t be represented in this encoding. (Python raises a UnicodeEncodeError exception in this case.) 

utf-8 (unicode transformation format) 
1 If the code point is <128, it’s represented by the corresponding byte value. 
2 If the code point is between 128 and 0x7ff, it’s turned into two byte values between 128 and 255. 
3 Code points >0x7ff are turned into three- or four-byte sequences, where each byte of the sequence is between 128 and 255. 

Разница между ул и Юникода объектов:

Вы можете сказать, что это ул baiscally строка байт и юникода является строкой Юникода. Оба могут иметь различную кодировку, такую ​​как ascii или utf-8.

str vs. unicode 
1 str  = byte string (8-bit) - uses \x and two digits 
2 unicode = unicode string  - uses \u and four digits 
3 basestring 
     /\ 
    /\ 
    str unicode 

Если вы будете следовать некоторым простым правилам, вы должны идти в порядке с обработкой объектов ул/Юникода в различных кодировках, как ASCII или UTF-8 или любой кодировке, вы должны использовать:

Rules 
1 encode(): Gets you from Unicode -> bytes 
    encode([encoding], [errors='strict']), returns an 8-bit string version of the Unicode string, 
2 decode(): Gets you from bytes -> Unicode 
    decode([encoding], [errors]) method that interprets the 8-bit string using the given encoding 
3 codecs.open(encoding=”utf-8″): Read and write files directly to/from Unicode (you can use any encoding, not just utf-8, but utf-8 is most common). 
4 u”: Makes your string literals into Unicode objects rather than byte sequences. 
5 unicode(string[, encoding, errors]) 

Предупреждение: Не используйте encode() для байтов или декодировать() для объектов Unicode.

И снова: программное обеспечение должно работать только со строками Unicode внутри, преобразовывая его в конкретную кодировку на выходе.

Смежные вопросы

 Смежные вопросы