2009-01-30 3 views
13

Я пишу сценарий, который должен перемещать некоторый файл вокруг, но, к сожалению, это не кажется os.path играет с интернационализацией очень хорошо. Когда у меня есть файлы, названные на иврите, есть проблемы. Вот скриншот содержимого каталога:Os.path Python задыхается на иврите filenames

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

ответ

15

Хм, после того, как some digging представляется, что при поставке ОС.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) хранит все имена файлов в unicode
  • os.listdir (и аналогичные функции, такие как os.walk) shoul d передается строка юникода для правильной работы с путями unicode. Вот цитата из упомянутой выше ссылки:

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

  • И, наконец, print хочет строку ASCII, а не Unicode, так что путь должен быть закодирован в формате ASCII.
+0

Несмотря на то, что печать по-прежнему невелика в отношении ascii на всех средах. См. Мой ответ. – PEZ

+0

У печати нет проблем при печати unicode: проблема может быть в кодировке stdout. Если консоль является unicode, проблем нет, иначе требуется явный код. – piro

+0

Отлично. Это означает, что вы можете сообщать о правильных именах файлов в Windows, если вы печатаете в дескриптор файла с правильным набором кодировок. Обработчик ошибок «replace» просто сигнализирует о моем поражении. =) – PEZ

3

Это выглядит как Unicode против выпуска ASCII - os.listdir возвращает список ASCII строк.

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

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

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

+0

Я думаю, я мог бы попробовать, но это не поможет мне, поскольку я не могу перейти на 3.0 в настоящий момент. Я уверен, что должно быть решение для 2.5 –

1

Он работает как шарм, используя 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 запас командной строки приложения), что есть. Используя IDLE, он все еще работал, но не корректно печатал имя файла. Для того, чтобы убедиться, что это действительно Юникода там я проверил:

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

. Я думаю, что это связано с тем, что Windows хранит все имена файлов в Unicode. см. мой собственный частичный ответ –

+0

На моей машине он также работает со строками unicode. – PEZ

+0

любопытно. если я просто передаю pf для печати, он выдает исключение кодировки. он должен ожидать ascii –

0

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

+0

Могу ли я сделать вывод на дисплей ветрового стекла unicode? что делает OSX, чтобы показать это красиво? –

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

  • Нет связанных вопросов^_^