Основная проблема заключается в непревращенном соединении между Unicode и байтовыми строками.Решения могут быть преобразованы в единый формат или избежать проблем, используя некоторые хитрости.Все мои решения включают стандартную библиотеку glob
и shutil
.
Для примера, у меня есть несколько имен файлов Unicode, заканчивающихся на ods
, и я хочу переместить их в подкаталог с именем א
(иврит алеф, символ Юникода).
Первое решение - указать имя каталога в виде байтовой строки:
>>> import glob
>>> import shutil
>>> files=glob.glob('*.ods') # List of Byte string file names
>>> for file in files:
... shutil.copy2(file, 'א') # Byte string directory name
...
Второе решение - преобразовать имена файлов в Unicode:
>>> import glob
>>> import shutil
>>> files=glob.glob(u'*.ods') # List of Unicode file names
>>> for file in files:
... shutil.copy2(file, u'א') # Unicode directory name
Кредит Ezio Melotti, Список ошибок Python .
Третье решение - избегать назначения целевого имени каталога Unicode
Хотя это не лучшее решение вНа мой взгляд, здесь есть хороший трюк, о котором стоит упомянуть.
Измените каталог на каталог назначения с помощью os.getcwd()
, а затем скопируйте в него файлы, указав его как .
:
# -*- coding: utf-8 -*-
import os
import shutil
import glob
os.chdir('א') # CD to the destination Unicode directory
print os.getcwd() # DEBUG: Make sure you're in the right place
files=glob.glob('../*.ods') # List of Byte string file names
for file in files:
shutil.copy2(file, '.') # Copy each file
# Don't forget to go back to the original directory here, if it matters
Более подробное объяснение
Простой подход shutil.copy2(src, dest)
терпит неудачу, потому что shutil
объединяет Unicode со строкой ASCII без преобразований:
>>> files=glob.glob('*.ods')
>>> for file in files:
... shutil.copy2(file, u'א')
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/python2.6/shutil.py", line 98, in copy2
dst = os.path.join(dst, os.path.basename(src))
File "/usr/lib/python2.6/posixpath.py", line 70, in join
path += '/' + b
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 1:
ordinal not in range(128)
Как было показано ранее, этого можно избежать при использовании 'א'
вместо Unicode u'א'
Это ошибка?
На мой взгляд, это ошибка, потому что Python не может ожидать, что basedir
имена будут всегда str
, а не unicode
.Я сообщил об этом как о проблеме в баглисте Python , и жду ответов.
Дополнительная информация
Официальный Unicode Python HOWTO