2016-07-25 2 views
-1

Насколько я знаю, концепция python имеет только допустимые символы в строке, но в моем случае ОС будет поставлять строки с неверными кодировками в именах путей, с которыми мне приходится иметь дело. Поэтому я заканчиваю строками, которые содержат символы, которые не являются юникодами.Как заменить недопустимые символы юникода в строке в Python?

Чтобы исправить эти проблемы, мне нужно как-то отобразить эти строки. К сожалению, я не могу напечатать их, потому что они содержат символы не-Юникода. Есть ли элегантный способ заменить эти символы каким-то образом, по крайней мере, получить представление о содержании строки?

Моей идеей было бы обработать эти строки символом по символу и проверить, действительно ли сохраненный символ является действительным юникодом. В случае недопустимого символа я хотел бы использовать определенный символ юникода. Но как я могу это сделать? Использование codecs кажется не подходящим для этой цели: у меня уже есть строка, возвращаемая операционной системой, а не массив байтов. Преобразование строки в массив байтов, по-видимому, включает в себя декодирование, которое, конечно, потерпит неудачу. Кажется, я застрял.

У вас есть советы для меня, как создать такую ​​заменяющую строку?

+0

Пожалуйста, включите строку выборки в вашем вопросе; используйте 'print repr (obj)' для создания образца. Вероятно, вы можете использовать подходящий режим 'errors', чтобы иметь место для заполнителей Python. –

+0

.decode ("utf-8", "ignore") игнорирует плохие символы. – les

+0

В оболочках bash я получаю вопросительные знаки в качестве замещающих символов. В менеджерах файлов я вижу инвертированный знак вопроса. –

ответ

0

Спасибо за ваши комментарии. Таким образом, я смог реализовать лучшее решение:

try: 
     s2 = codecs.encode(s, "utf-8") 
     return (True, s, None) 
    except Exception as e: 
     ret = codecs.decode(codecs.encode(s, "utf-8", "replace"), "utf-8") 
     return (False, ret, e) 

Просьба поделиться любыми улучшениями в этом решении. Спасибо!

0

У вас нет примера. Поэтому я рассмотрел один пример, чтобы ответить на ваш вопрос.

х = «Это кошка, которая выглядит хорошо ðŸ~Š» печать х x.replace («ðŸ~Š», «»)

выход: Это кошка, которая хорошо выглядит ðŸ~Š «Это кошка, которая выглядит хорошо»

+0

У меня нет конкретного примера о фактическом шаблоне байта, который привел к ошибкам в моем случае. Фильтр, который я пишу, намеревается идентифицировать проблемы кодирования Unicode в заданных строках.Один из способов, которым вы могли бы воспроизвести эту ситуацию, - это просто генерировать случайные данные, а затем попытаться интерпретировать эти данные как UTF-8. Вы, как правило, терпите неудачу, потому что эти двоичные данные, скорее всего, нарушат стандарт UTF-8. Извините, я не могу определить, как произошли эти нарушения. Я пытался идентифицировать существование как первый шаг. –

+0

вы можете попробовать это, если не знаете символы, отличные от юникода: try: string.decode ('utf-8') print "string is UTF-8, length% d bytes"% len (string) except UnicodeError: print "string is not UTF-8" – Chandan

+0

Да, но интересная часть начинается там, где мне не только хотелось бы определить, является ли строка Unicode или нет, но и фактически получить представление о самой строке путем фильтрации или замены ' символов ", которые являются недопустимыми .. –

1

Если у вас есть байтовой строка (недекодированные данные), используйте обработчик 'replace' ошибки. Например, если ваши данные (в основном) UTF-8 кодируются, то вы можете использовать:

decoded_unicode = bytestring.decode('utf-8', 'replace') 

и U+FFFD � REPLACEMENT CHARACTER символы будут вставлены для любых байтов, которые не могут быть декодированы.

Если вы хотите использовать другой символ замены, достаточно легко потом заменить их:

decoded_unicode = decoded_unicode.replace(u'\ufffd', '#') 

Демо:

>>> bytestring = 'F\xc3\xb8\xc3\xb6\xbbB\xc3\xa5r' 
>>> bytestring.decode('utf8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/mjpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0xbb in position 5: invalid start byte 
>>> bytestring.decode('utf8', 'replace') 
u'F\xf8\xf6\ufffdB\xe5r' 
>>> print bytestring.decode('utf8', 'replace') 
Føö�Bår 
+0

Ницца! Я не видел этого в документации: я бы хотел, чтобы такие функции были описаны более заметными. –

+0

Спасибо за помощь. Я обновил решение. –

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