Python расшифровка работает для меня, но не другие - PullRequest
4 голосов
/ 30 августа 2011

Я уверен, что на этот вопрос уже был дан ответ, но я понятия не имею, что искать. Моя проблема не столько моя, сколько всех остальных. Короче говоря, у меня есть скрипт на Python с декодированием текста, и он отлично декодирует для меня, но не работает для других пользователей, даже с тем же кодом и вводом.

Я написал скрипт ( источник в Bitbucket ), который преобразует SMS-сообщения Windows Mobile 6 (через вывод PIM Backup ) в SMS-сообщения Android (ввод через SMS Backup & Resotre ) путем преобразования содержимого резервной копии PIM в формат SMSB & R-совместимый XML.

Теперь PIM Backup выводит свое содержимое в формате Little Endian UCS-2, что приятно, поскольку он поддерживает все виды международных разговоров. В моем скрипте я загружаю контент, используя встроенное в Python декодирование строк, и создаю объект для чтения csv с помощью:

# Read the file contents
sms_text = csv_file.read().decode('utf-16').split(os.linesep)
sms_reader = csv.reader(sms_text, delimiter=';', quotechar='"', escapechar='\\')

Затем я обрабатываю каждую строку программы для чтения csv:

row = sms_reader.next()

У меня это в блоке try, потому что очень редко он выбрасывает UnicodeEncodeError, когда что-то не так. Но опять же, это очень редко для меня.

Моя проблема в том, что, похоже, это все время выдается все время для других пользователей моего сценария, использующих символы не-ASCII в своих SMS-сообщениях. Немецкий пользователь недавно связался со мной, сказав, что только около 10% его SMS-сообщений были правильно декодированы. Он прислал мне свой файл .pib, я проверил его по сценарию, и у меня не было ни одной проблемы с конвертацией. Весь вывод казался стандартным ANSI / ISO 8859-1 / Windows-1252 / чем угодно, так что вряд ли экзотика.

Мой вопрос: почему эти пользователи не могут декодировать свои входные данные, когда у меня нет проблем, используя точно такой же код (и версию Python)? И как продолжение, что я могу сделать, чтобы изменить мой сценарий, чтобы он работал для всех?

РЕДАКТИРОВАТЬ: я не упомянул один важный момент: я запускаю скрипт в Eclipse с использованием PyDev. Когда я запускаю его в командной строке, он выдает все те же проблемы, что и для всех остальных! Я до сих пор не знаю, в чем проблема, но, надеюсь, это поможет сузить ее.

Пример очень простого файла .csm (извлеченного из файла .pib, измененные имена и номера) с нестандартными символами будет следующим:

Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"491703000000";"491703000000";;"";"Wir wünschen dem rainer alles gute und viel gesundheit! Bis nächste woche, wir hören uns bis dahin noch mal.. Liebe grüße aus md!";"";0;"\\%MDF3";"SMS";"IPM.SMStext";;;33;262144;2007,09,23,19,44,32;2007,09,23,19,44,31;1;"851980\;Gela\;+491739000000\;1\;0\;SMS";0;""

Нетрудно точно понять, в чем проблема, просто работая с этой строкой, поскольку я сам не испытываю исключения.

Другой пример, в котором у do есть проблемы (даже в Eclipse), следующий:

Msg Id;Sender Name;Sender Address;Sender AddressType;Prefix;Subject;Body;BodyType;Folder;Account;Msg Class;Content Length;Msg Size;Msg Flags;Msg Status;Modify Time;Delivery Time;Recipient Nbr;Recipients;Attachment Nbr;Attachments
0x00,0x00;"Jonas/M";"\"Jonas/M\" <+46737000000>";;"";"Den går 28 ";"";2;"\\%MDF4";"SMS";"IPM.SMStext";0;24;0;0;2011,03,12,21,15,19;2011,03,12,21,16,17;0;"";0;""
0x00,0x00;"Don Vär";"\"Don Vär\" <+46709000000>";;"";"försöke® dhdjhdhhdjehdejehţýùhbfvfghjujhuikjkłánjajnxsjajmsxnsmajmkjsnshdjnsjmwkjhdnjsjmwkjdhjjdewjjwjwjw®";"";2;"\\%MDF1";"SMS";"IPM.SMStext";0;212;1;0;2010,05,17,15,56,49;2010,05,17,15,55,46;0;"";0;""

Трассировка исключения:

Traceback (most recent call last):
  File "C:\Programming\workspace\pim2smsbr\src\pim2smsbr.py", line 207, in <module>
    convert(args.source[0], args.out)
  File "C:\Programming\workspace\pim2smsbr\src\pim2smsbr.py", line 98, in convert
    row = sms_reader.next()
  File "C:\Python27\lib\encodings\cp1252.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_table)
UnicodeEncodeError: 'charmap' codec can't encode character u'\ue403' in position 77: character maps to <undefined> 

UPDATE:

Ответ Джона Мачина, приведенный ниже, приносит удовольствие. Я просто поменял одну строчку и все хорошо. Изменения:

sms_text = csv_file.read().decode('utf-16').split(os.linesep)

Кому:

sms_text = csv_file.read().decode('utf-16').encode('utf-8').splitlines()

1 Ответ

2 голосов
/ 30 августа 2011

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

Важен тот факт, что вы иногда получаете UnicodeEncodeError (обратите внимание, что Encode not Decode). Хотите изменить свой код для отображения точного сообщения об ошибке и трассировки, которые вы получаете, вместо того, чтобы подавлять их?

Работаете ли вы в Linux / OSX / Windows? Если окна, в окне командной строки? Если так, что говорит команда CHCP? О чем это говорит ваш немецкий корреспондент?

Вы читали, что говорят CSV-документы о Unicode? Вот что происходит:

>>> import csv
>>> r = csv.reader([u"\xA0"])
>>> r.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)
>>>

У вас гораздо больше шансов заставить это работать, если вы выполните следующие шаги:

  1. читать необработанные байты в файле
  2. декодировать строку байтов в Unicode, используя UTF-16
  3. кодирует строку Unicode в UTF-8
  4. разбить строку UTF-8 на список строк (используйте str.splitlines())
  5. сделать из этого списка программу для чтения csv
  6. перебирает строки, декодируя каждую ячейку из UTF-8 в Unicode.

Обновление Я ничего не вижу в ваших изменениях вашего вопроса, чтобы заставить меня изменить мой предыдущий совет. У вас есть выбор пропустить шаг 6 выше (это будет работать, но это зло) или включить шаг 6 и переписать фазу вывода, чтобы использовать [c]ElementTree или lxml для кодирования UTF-8, экранирования и т. Д. Кстати , вы пишете файлы XML, которые говорят, что они закодированы в UTF-8. Я не могу воспроизвести это, потому что у меня нет Eclipse, но я подозреваю, что XML-файлы, которые вы пишете "OK" при работе в Eclipse, на самом деле кодируются в cp1252. Вы пробовали их с помощью валидатора XML?

Ваша проблема с символом U + E403 является лишь частью проблемы, заключающейся в том, что ваш сценарий будет «работать» только с символами, представленными в любой кодировке, которую выбирает модуль csv, когда сталкивается с вводом unicode. Этот символ находится в одном из блоков PUA (Private User Area), выделенных для материала, относящегося к конкретному поставщику (например, символ Apple), или содержимого приложения. Он не покрыт ни одной из предоставленных кодировок Python и не может быть правильно отрисован (потому что он не опубликован шрифтом). поиск в Google («emoji E403») и следование полученным выводам указывают на то, что это может быть U + 1F614 PENSIVE FACE, новинка в Unicode 6.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...