Сценарий Python не может правильно кодировать специальные символы Unicode

Я конвертирую текстовый файл (words.txt), который в основном является словарем в этом формате:

good morning, Góðan daginn

в файл json (converted.json) в этом формате

{
    "wordId": 1,
    "word": "good morning",
    "translation": "Góðan daginn"
}

Преобразование из текстового файла в файл json работает совершенно нормально и, как и ожидалось, но кодировка символов несколько испорчена, и вот как:

для кодирования этого символа ð вместо этого \u00f0 сценарий кодирует этот символ следующим образом: \u00c3\u00b0

Вопрос: как исправить и/или настроить скрипт, чтобы он правильно кодировал эти специальные символы? имея в виду, что эти символы в основном исландские/скандинавские, и я использую PyCharm в качестве IDE.

PS Пожалуйста, примите во внимание, что мои навыки Python немного ограничены!!

Это скрипт converter.py:

import json

with open('words.txt', 'r') as f_in, \
    open('converted.json', 'w') as f_out:
cnt = 1
data = []
for line in f_in:
    line = line.split(',')
    if len(line) != 2:
        continue
    d = {"wordId": cnt, "word": line[0].strip(), "translation": line[1].strip()}
    data.append(d)
    cnt += 1

f_out.write(json.dumps(data, indent=4))

Я использую Python 3


person Thorvald Olavsen    schedule 30.11.2019    source источник
comment
Если это Python 2, вам нужно декодировать строки из вашего файла, используя .decode('utf-8'), потому что в противном случае вы получаете необработанные байтовые строки. (Python 3 предотвращает эту ошибку — настоятельно рекомендуется перейти на Python 3 для любого нового кода!)   -  person nneonneo    schedule 30.11.2019
comment
@nneonneo Я только что пробовал с Python 3 и Jupyter, и все равно получаю тот же неправильный результат! что-нибудь еще я могу сделать?   -  person Thorvald Olavsen    schedule 30.11.2019
comment
Python по умолчанию использует UTF-8, а ð в utf-8 имеет код \u00c3\u00b0. Он имеет код \u00f0 в Latin-1 См. print( 'ð'.encode('latin-1') )   -  person furas    schedule 30.11.2019
comment
@furas Я попробовал это "translation": line[1].strip().encode('latin-1'), но получил следующую ошибку: UnicodeEncodeError: 'latin-1' codec can't encode character '\u201c' in position 2: ordinal not in range(256)   -  person Thorvald Olavsen    schedule 30.11.2019
comment
возможно, вам нужна другая кодировка - т.е. latin2, cp1250, cp1251, cp1252 и т. д., iso8859-2 и т. д. — некоторые символы могут иметь одинаковый код в разной кодировке. См. таблицу Стандартные кодировки.   -  person furas    schedule 30.11.2019
comment
print( 'ð\u201c'.encode('cp1252') ) дает b'\xf0\x93'   -  person furas    schedule 30.11.2019
comment
Кстати: mac_iceland тоже работает, но дает другие коды print('ð\u201c'.encode('mac_iceland'))   -  person furas    schedule 30.11.2019
comment
@furas сгенерированный файл json будет использоваться в приложении .Dart, поэтому лучше, если я вставлю латиницу-1   -  person Thorvald Olavsen    schedule 30.11.2019
comment
Я не использую Dart, но я бы удивился, если бы мне понадобился utf-8 :)   -  person furas    schedule 30.11.2019


Ответы (1)


Я считаю, что проблема в том, что json.dumps вам может понадобиться использовать ensure_ascii=False. Нравиться:

f_out.write(json.dumps(data, indent=4, ensure_ascii=False))

Итак, в основном, как говорится в документе:

Если sure_ascii имеет значение true (по умолчанию), в выводе гарантированно будут экранированы все входящие символы, отличные от ASCII. Если sure_ascii имеет значение false, эти символы будут выводиться как есть.

person Sraw    schedule 30.11.2019