Исключение Python IOError при распаковке архива с глубокой структурой каталогов

У меня возникает следующая ошибка при попытке извлечь zip-файл с помощью метода extractall модуля zipfile:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\zipfile.py", line 964, in extractall
self.extract(zipinfo, path, pwd)
File "C:\Python27\lib\zipfile.py", line 952, in extract
return self._extract_member(member, path, pwd)
File "C:\Python27\lib\zipfile.py", line 996, in _extract_member
target = file(targetpath, "wb")

IOError: [Errno 2] No such file or directory: 'D:\\GITHUBDB\\C++\\FellowTraveler
_Open-Transactions\\FellowTraveler-Open-Transactions-846a939\\sample-data\\no_ba
skets\\client_data\\purse\\tBy5mL14qSQXCJK7Uz3WlTOKRP9M0JZksA3Eg7EnnQ1\\T1Q3wZWg
eTUoaUvn9m1lzIK5tn5wITlzxzrGNI8qtaV\\CvHGtfOOKzQKL5hFL7J4iF5yAodVKhS1rxPzME5R9XA'

Это происходит из-за ограничения Windows на 260 символов пути. Делать cd не вариант, большая часть пути идет из самого архива. Я читал о префиксе "\\?\", но добавление его в параметр extractall не работает, оно не работает в os.mkdir внутри модуля zipfile.

Исправление zipfile.py с помощью «\\?\» кажется возможным, но уродливым решением.

Любые идеи, пожалуйста?


person Yuri Vorotilov    schedule 28.10.2012    source источник
comment
Извлеките его в корень D:, или не используйте полные пути, или старайтесь использовать разумные имена каталогов.   -  person Burhan Khalid    schedule 29.10.2012
comment
Я не могу использовать другие имена каталогов :), потому что архивы из внешнего источника. Распаковка в D:\ сэкономит мне всего 13 символов... не поможет.   -  person Yuri Vorotilov    schedule 29.10.2012
comment
Вы можете подкласс ZipFile переопределить _extract_member. Возможно, обрезать все длинные имена каталогов до 10 символов + хэш исходного имени для уникальности.   -  person Eryk Sun    schedule 29.10.2012
comment
Вам нужно все дерево или только файлы?   -  person Burhan Khalid    schedule 29.10.2012


Ответы (2)


В Windows есть способ поддерживать длинные пути к файлам. Просто убедитесь, что ваш путь юникодный, абсолютный и добавьте префикс \\?\. Например:

zip = ZipFile(zip_filename)
zip.extractall(u'\\\\?\\D:\\a_long_path')

Я протестировал его с классом ZipFile на python 2.7, и он отлично работает.

Подробнее об именовании файлов в Windows см. здесь.

person Tzach    schedule 12.06.2014

Мне не нужно было кодировать путь в юникоде, но я должен изменить путь на абсолютный путь и добавить «\\?\» перед этим абсолютным путем.

person edy    schedule 18.07.2016