Преобразование исходной строки байтов в Юникод, не зная кодовой страницы заранее
При использовании контекстного контекстного меню окна пропускают путь к файлу как необработанный (байтовый) тип строки.
Например:
path = 'C:\\MyDir\\\x99\x8c\x85\x8d.mp3'
Многие внешние пакеты в моем приложении ожидают строки типа unicode
, поэтому я должен преобразовать их в unicode
.
Это было бы легко, если бы мы заранее знали кодировку исходной строки (в примере это cp1255
). Однако я не могу знать, какая кодировка будет использоваться локально на каждом компьютере по всему миру.
Как преобразовать string
в unicode
? Возможно, требуется использовать win32api
?
Ответы
Ответ 1
Не знаю, почему вы можете получить кодовую страницу DOS (862) вместо ANSI (1255) - как настроен параметр правой кнопки мыши?
В любом случае - если вам нужно принять любой произвольный символ Юникода в своих аргументах, вы не сможете сделать это из Python 2 sys.argv
. Этот список заполняется из байтов, возвращаемых версией Win32 API, отличной от Unicode (GetCommandLineA
), и эта кодировка никогда не защищена от Unicode.
Многие другие языки, включая Java и Ruby, находятся в одной лодке; ограничение исходит из реализаций исполнения Microsoft C стандартных функций библиотеки C. Чтобы исправить это, можно было бы назвать версию Unicode (GetCommandLineW
) в Windows вместо того, чтобы полагаться на межплатформенную стандартную библиотеку. Python 3 делает это.
Тем временем для Python 2 вы можете сделать это, вызвав GetCommandLineW
самостоятельно, но это не особенно красиво. Вы также можете использовать CommandLineToArgvW
, если хотите параметр splattng в стиле Windows. Вы можете сделать это с помощью расширений win32
, а также просто ctypes
.
Пример (хотя шаг кодирования строки Unicode обратно в байты UTF-8 лучше всего пропустить).
Ответ 2
Обычно я использую собственную функцию утилиты для безопасного преобразования из обычных кодовых страниц в unicode. Для чтения кодировки по умолчанию, вероятно, функция locale.getpreferredencoding может помочь (http://docs.python.org/2/library/locale.html#locale.getpreferredencoding).
Пример функции util, которая пытается преобразовать в unicode путем итерации некоторых предопределенных кодировок:
# coding: utf-8
def to_unicode(s):
if isinstance(s, unicode): return s
from locale import getpreferredencoding
for cp in (getpreferredencoding(), "cp1255", "cp1250"):
try:
return unicode(s, cp)
except UnicodeDecodeError:
pass
raise Exception("Conversion to unicode failed")
# or fallback like:
# return unicode(s, getpreferredencoding(), "replace")
print (to_unicode("addđšđč枎ŠĐ"))
Откат может быть разрешен с помощью ошибки аргумента функции unicode = "replace". Ссылка http://docs.python.org/2/library/functions.html#unicode
Для преобразования обратно в некоторую кодовую страницу вы можете проверить этот.