Как обработать undecodable имена файлов в Python?

Я действительно хотел бы иметь свое соглашение о приложении Python исключительно со строками Unicode внутренне. Это шло хорошо у меня в последнее время, но я столкнулся с проблемой с обработкой путей. API POSIX для файловых систем не является Unicode, таким образом, это возможно (и на самом деле несколько распространено) для файлов, чтобы иметь "undecodable" имена: имена файлов, которые не кодируются в установленном кодировании файловой системы.

В Python это проявляет как смесь unicode и str объекты, возвращаемые из os.listdir().

>>> os.listdir(u'/path/to/foo')
[u'bar', 'b\xe1z']

В том примере, символе '\xe1' кодируется в латинском 1 или somesuch, даже когда (гипотетическая) файловая система сообщает sys.getfilesystemencoding() == 'UTF-8' (в UTF-8 тот символ составил бы два байта '\xc3\xa1'). Поэтому Вы доберетесь UnicodeErrors повсеместно, при попытке использовать, например, os.path.join() с путями Unicode, потому что имя файла не может декодироваться.

ПРАКТИЧЕСКОЕ РУКОВОДСТВО Unicode Python дает этот совет о unicode путях:

Обратите внимание, что в большинстве случаев, API Unicode должны использоваться. API байтов должны только использоваться в системах, где undecodable имена файлов могут присутствовать, т.е. системы Unix.

Поскольку я главным образом забочусь о системах Unix, это означает, что я должен реструктурировать свою программу для контакта только со строками байтов для путей? (Если так, как я могу поддержать совместимость Windows?) Или там другой, лучшие способы иметь дело с undecodable именами файлов? Действительно ли они достаточно редки "в дикой природе", что я должен просто попросить, чтобы пользователи переименовали свои проклятые файлы?

(Если лучше просто иметь дело со строками байтов внутренне, у меня есть последующий вопрос: Как я храню строки байтов в SQLite для одного столбца при хранении остальной части данных как дружественные строки Unicode?)

9
задан adrian 4 August 2010 в 09:05
поделиться

2 ответа

В Python есть решение проблемы, если вы готовы перейти на Python 3.1 или более позднюю версию:

PEP 383 - Non-decodable Bytes in System Character Interfaces.

5
ответ дан 3 November 2019 в 04:40
поделиться

Если вам нужно хранить строки байтов в базе данных, предназначенной для UNICODE, то, вероятно, проще записать строки байтов в шестнадцатеричной кодировке. Таким образом, строку в шестнадцатеричном коде можно безопасно хранить как строку Unicode в базе данных.

Что касается проблемы имени пути UNIX, я понимаю, что для имен файлов не применяется конкретная кодировка, поэтому вполне возможно использовать Latin-1, KOI-8-R, CP1252 и другие в различных файлах. Это означает, что каждый компонент в имени пути может иметь отдельную кодировку.

У меня возникнет соблазн попытаться угадать кодировку имен файлов, используя что-то вроде модуля chardet . Конечно, нет никаких гарантий, поэтому вам все равно придется обрабатывать исключения, но у вас будет меньше некодируемых имен. Некоторые программы заменяют некодируемые символы на? что необратимо. Я бы предпочел, чтобы их заменили на \ xdd или \ xdddd, потому что при необходимости это можно поменять вручную. В некоторых приложениях можно представить строку пользователю, чтобы он мог ввести символы Юникода для замены некодируемых.

Если вы пойдете по этому пути, вы можете в конечном итоге расширить chardet для выполнения этой работы. Было бы неплохо дополнить его утилитой, которая сканирует файловую систему, находит недекодируемые имена и создает список, который можно редактировать, а затем отправлять обратно, чтобы исправить все имена с помощью эквивалентов Unicode.

2
ответ дан 3 November 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: