Python os.path задыхается от имен иврита

Я пишу script, который должен перемещать некоторый файл, но, к сожалению, он не выглядит так хорошо, как t20 > с интернационализацией. Когда у меня есть файлы, названные на иврите, есть проблемы. Здесь снимок экрана содержимого каталога:

alt text http://eli.thegreenplace.net/files/temp/hebfilenameshot.png

Теперь рассмотрим этот код, который просматривает файлы в этом каталоге:

files = os.listdir('test_source')

for f in files:
    pf = os.path.join('test_source', f)
    print pf, os.path.exists(pf)

Вывод:

test_source\ex True
test_source\joe True
test_source\mie.txt True
test_source\__()'''.txt True
test_source\????.txt False

Обратите внимание, что os.path.exists думает, что файл с ивритским именем даже не существует? Как я могу это исправить?

ActivePython 2.5.2 в Windows XP Home SP2

Ответ 1

Hmm, после некоторое копирование, кажется, что при поставке os.listdir строки в Юникоде этот вид работает:

files = os.listdir(u'test_source')

for f in files:

    pf = os.path.join(u'test_source', f)
    print pf.encode('ascii', 'replace'), os.path.exists(pf)

=== >

test_source\ex True
test_source\joe True
test_source\mie.txt True
test_source\__()'''.txt True
test_source\????.txt True

Некоторые важные замечания здесь:

  • Windows XP (как и все производные от NT) хранит все имена файлов в юникоде
  • os.listdir (и аналогичные функции, такие как os.walk), должны быть переданы строкой unicode для правильной работы с путями unicode. Здесь цитата из вышеупомянутой ссылки:

os.listdir(), который возвращает имена файлов, возникает проблема: следует ли вернуть Unicode-версия имен файлов или если он вернет 8-битные строки содержащие кодированные версии? os.listdir() будет делать оба, в зависимости о том, предоставили ли вы каталог путь как 8-битная строка или Unicode строка. Если вы передадите строку Unicode как путь, имена файлов будут декодированы используя кодировку файловой системы и список строк Unicode будет возвращается, передавая 8-битный путь вернет 8-битные версии имена файлов.

  • И, наконец, print хочет строку ascii, а не unicode, поэтому путь должен быть закодирован в ascii.

Ответ 2

Похоже, что проблема Unicode vs ASCII - os.listdir возвращает список строк ASCII.

Изменить: я попробовал это на Python 3.0, также на XP SP2, а os.listdir просто пропустил имена файлов на иврите, а не листинг их вообще.

В соответствии с документами это означает, что он не смог его декодировать:

Обратите внимание, что когда os.listdir() возвращает список строк, имена файлов, которые не могут быть правильно декодированными, опущены чем повышение UnicodeError.

Ответ 3

Он работает как шарм, используя Python 2.5.1 в OS X:

subdir/bar.txt True
subdir/foo.txt True
subdir/עִבְרִית.txt True

Возможно, это означает, что это как-то связано с Windows XP?

EDIT: Я также попытался использовать строки в Юникоде, чтобы лучше повторить поведение Windows:

for f in os.listdir(u'subdir'):
  pf = os.path.join(u'subdir', f)
  print pf, os.path.exists(pf)

subdir/bar.txt True
subdir/foo.txt True
subdir/עִבְרִית.txt True

В терминале (приложение командной строки os x stock). Используя IDLE, он все еще работал, но не корректно печатал имя файла. Чтобы убедиться, что это действительно юникод, я проверил:

>>>os.listdir(u'listdir')[2]
u'\u05e2\u05b4\u05d1\u05b0\u05e8\u05b4\u05d9\u05ea.txt'

Ответ 4

Знак вопроса - это более или менее универсальный символ, отображаемый, когда символ Юникода не может быть представлен в конкретной кодировке. Возможно, ваш терминал или интерактивный сеанс под Windows используют ASCII или ISO-8859-1 или что-то в этом роде. Таким образом, фактическая строка является unicode, но она переводится на???? при печати на терминал. Вот почему он работает для PEZ, используя OSX.