Что касается проекта, над которым я работаю, у меня есть много файлов .unl (informix) для разных стран, и их необходимо импортировать в postgres. Для этого мне нужно перевести схему Informix в схему Postgres с помощью Python.
Предполагая, что в моем скрипте Python есть эта строка кода, с помощью которой я хочу открыть все файлы .unl:
open(file, 'r', encoding='latin1')
В странах, где используется encoding = latin1
, скрипт работает нормально, и в Postgres все выглядит хорошо. За исключением Польши
Когда я указываю encoding = latin2
для Польши, скрипт импорта по-прежнему успешно выполняется, но польский текст в Postgres выглядит по-другому. Например, вывод неожиданно выглядит так:
Но если кодировка правильная, ожидаемый результат должен выглядеть так:
Я попробовал и до сих пор не могу понять, как это исправить. Я очень ценю любые предложения о том, как решить эту проблему. Заранее спасибо!
Опубликуйте минимальный воспроизводимый пример включая образец файла. Вы проверили локаль базы данных с помощью sysdbslocale
?
Определенно похоже на проблему с кодировкой символов, но ваш пример не имеет особого смысла. Попробуйте запустить этот код во входном файле на польском языке: stackoverflow.com/a/1779263/5987
Не верьте, что до или после не было никаких обращений. Возможно, исходные данные были латиницей-2, но при «копировании файлов» было недокументированное перекодирование. То же самое и с выводом: не ожидайте, что все программы знают выходную кодировку для правильного отображения (кодировка — это метаданные, поэтому такие данные теряются или не передаются между программами). Итак, первый комментарий: проверьте raw
байты: прочитайте как двоичные и выведите значения каждого символа (и, возможно, некоторых старых страниц cp (то есть со всеми символами с другим и определенным числом, а также в управляющих кодах): это помогает найти, где находится проблема в том, что без предположения
Благодарим всех за то, что поделились своими мыслями. Теперь эта проблема решена.
Вы столкнулись с вопиющим случаем моджибаке.
Доказательство в следующем (частично прокомментированном) фрагменте кода: type .\SO\78540135.py
file = r'.\SO\78540135.txt' str_text = 'Aleksańdra Świętochowskiego' # create a sample file: utf-8 encoded with open( file, 'w', encoding = 'utf-8') as f: f.write( str_text) # read the file using wrong encoding with open( file, 'r', encoding = 'latin2') as f: str_name = f.read() print( '\nmojibake', str_name) # read the file using correct encoding with open( file, 'r', encoding = 'utf-8') as f: str_name = f.read() print( '\nUTF8text', str_name)
Вывод: python .\SO\78540135.py
mojibake AleksaĹdra ĹwiÄtochowskiego UTF8text Aleksańdra Świętochowskiego
Спасибо @JosefZ за то, что рассказал мне об этом, и да, это проблема моджибаке. Благодаря вашему упоминанию я нашел решения. Еще раз спасибо!
@ Lotus1989 отлично! чтобы помочь сообществу и заработать немного репутации, отметьте это как ответ, поставив галочку слева.
Меня смутил тот факт, что ожидаемая строка и результат моджибаке были одинаковой длины; Я предполагал, что преобразование в UTF-8 удлинит строку. Так и есть, но оказывается, что некоторые символы, полученные после декодирования latin2, невидимы!
@MarkRansom да, эти невидимки — это элементы управления между \x80
и \x9F
. На самом деле, 'ń Ś ę'.encode( 'utf-8').decode( 'latin2')
-> 'Ĺ\x84 Ĺ\x9a Ä\x99'
однако print( 'Ĺ\x84 Ĺ\x9a Ä\x99')
-> Ĺ Ĺ Ä
…
как и для всех вопросов такого рода, посмотрите на необработанное байтовое представление файла/строки и проверьте фактическую кодировку, исследуя байты некоторых специальных символов, если файл действительно соответствует ISO-8859. -2 тогда
open('file', 'r', encoding='ISO-8859-2')
должно работать