Преобразование имен файлов Python в Unicode

Я на Python 2.6 для Windows.

Я использую os.walk для чтения файлового дерева. Файлы могут содержать не 7-битные символы (например, немецкое "ae") в именах файлов. Они закодированы во внутреннем строковом представлении Pythons.

Я обрабатываю эти имена файлов с помощью функций библиотеки Python, и это не удается из-за неправильной кодировки.

Как я могу преобразовать эти имена файлов в правильные (Unicode?) Строки Python?

У меня есть файл "d:\utest\ü.txt". Передача пути как Unicode не работает:

>>> list(os.walk('d:\\utest'))
[('d:\\utest', [], ['\xfc.txt'])]
>>> list(os.walk(u'd:\\utest'))
[(u'd:\\utest', [], [u'\xfc.txt'])]

6 ответов

Решение

Если вы передаете строку Unicode os.walk(), вы получите результаты Unicode:

>>> list(os.walk(r'C:\example'))          # Passing an ASCII string
[('C:\\example', [], ['file.txt'])]
>>> 
>>> list(os.walk(ur'C:\example'))        # Passing a Unicode string
[(u'C:\\example', [], [u'file.txt'])]

Я искал решение для Python 3.0+. Поставит это здесь, если это кому-то еще нужно.

rootdir = r'D:\COUNTRY\ROADS\'
fs_enc = sys.getfilesystemencoding()
for (root, dirname, filename) in os.walk(rootdir.encode(fs_enc)):
    # do your stuff here, but remember that now
    # root, dirname, filename are represented as bytearrays

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

unicode_name = unicode(filename, "utf-8", errors="ignore")

пойти другим путем,

unicode_name.encode("utf-8")
os.walk(unicode(root_dir, 'utf-8'))

os.walk не указано, чтобы всегда использовать os.listdir, но также не указано, как обрабатывается Unicode. Тем не мение, os.listdir говорит:

Изменено в версии 2.3: В Windows NT/2k/XP и Unix, если путь - это объект Unicode, результатом будет список объектов Unicode. Не декодируемые имена файлов будут по-прежнему возвращаться как строковые объекты.

Работает ли просто использование аргумента Unicode для вас?

for dirpath, dirnames, filenames in os.walk(u"."):
  print dirpath
  for fn in filenames:
    print "   ", fn

Нет, они не закодированы во внутреннем строковом представлении Pythons, такого нет. Они кодируются в кодировке операционной системы / файловой системы. Переход на Unicode работает для Os.Walk, хотя.

Я не знаю, как ведет себя os.walk, когда имена файлов не могут быть декодированы, но я предполагаю, что вы получите строку обратно, как с os.listdir(). В этом случае у вас снова будут проблемы позже. Кроме того, не вся стандартная библиотека Python 2.x будет правильно принимать параметры Юникода, поэтому вам может понадобиться закодировать их как строки в любом случае. Таким образом, проблема на самом деле может быть где-то еще, но вы заметите, если это так.;-)

Если вам нужно больше контроля над декодированием, вы не всегда можете передать строку, а затем просто расшифруйте ее с именем файла = filename.decode() как обычно.

Другие вопросы по тегам