Zipfile / shutil.make_archive генерирует EncodeError для немецких умлаутов - PullRequest
1 голос
/ 28 сентября 2019

Я пытаюсь сжать папку в Python 3 с помощью модуля zipfile.

Поскольку я немец, у меня есть несколько имен файлов, содержащих умляуты (äöü).

Во время архивированияЯ получаю UnicodeEncodeError: 'utf-8' codec can't encode character '\udcfc' in position 95: surrogates not allowed.

Рассматриваемый символ ü.

Как мне получить zipfile, чтобы сжать все мои файлы?

соответствующий код:

def zipdir(path, ziph):
    for root, dirs, files in os.walk(path):
        for file in files:
            ziph.write(os.path.join(root, file))

if __name__ == '__main__':
    zipf = zipfile.ZipFile('path/to/destination', 'w', zipfile.ZIP_DEFLATED)
    zipdir('path/to/folder', zipf)
    zipf.close()

Редактировать:
При использовании shutil.make_archive.

import shutil

shutil.make_archive('/path/to/destination', 'zip', '/path/to/folder')

возникает та же ошибкаПолная трассировка стека shutil.make_archive():

Traceback (most recent call last):
  File "/usr/lib64/python3.7/zipfile.py", line 452, in _encodeFilenameFlags
    return self.filename.encode('ascii'), self.flag_bits
UnicodeEncodeError: 'ascii' codec can't encode character '\udcfc' in position 59: ordinal not in range(128)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "run.py", line 39, in <module>
    archive_dir(path, zip_fullpath)
  File "run.py", line 19, in archive_dir
    shutil.make_archive(dest, 'zip', source)
  File "/home/sean/.local/share/virtualenvs/backup-script-QUcRKrDQ/lib/python3.7/shutil.py", line 822, in make_archive
    filename = func(base_name, base_dir, **kwargs)
  File "/home/sean/.local/share/virtualenvs/backup-script-QUcRKrDQ/lib/python3.7/shutil.py", line 720, in _make_zipfile
    zf.write(path, path)
  File "/usr/lib64/python3.7/zipfile.py", line 1746, in write
    with open(filename, "rb") as src, self.open(zinfo, 'w') as dest:
  File "/usr/lib64/python3.7/zipfile.py", line 1473, in open
    return self._open_to_write(zinfo, force_zip64=force_zip64)
  File "/usr/lib64/python3.7/zipfile.py", line 1586, in _open_to_write
    self.fp.write(zinfo.FileHeader(zip64))
  File "/usr/lib64/python3.7/zipfile.py", line 442, in FileHeader
    filename, flag_bits = self._encodeFilenameFlags()
  File "/usr/lib64/python3.7/zipfile.py", line 454, in _encodeFilenameFlags
    return self.filename.encode('utf-8'), self.flag_bits | 0x800
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcfc' in position 59: surrogates not allowed

Полная трассировка стека zipfile:

Traceback (most recent call last):
  File "/usr/lib64/python3.7/zipfile.py", line 452, in _encodeFilenameFlags
    return self.filename.encode('ascii'), self.flag_bits
UnicodeEncodeError: 'ascii' codec can't encode character '\udcfc' in position 95: ordinal not in range(128)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "run.py", line 41, in <module>
    zipdir(path, zipf)
  File "run.py", line 16, in zipdir
    ziph.write(filepath)
  File "/usr/lib64/python3.7/zipfile.py", line 1746, in write
    with open(filename, "rb") as src, self.open(zinfo, 'w') as dest:
  File "/usr/lib64/python3.7/zipfile.py", line 1473, in open
    return self._open_to_write(zinfo, force_zip64=force_zip64)
  File "/usr/lib64/python3.7/zipfile.py", line 1586, in _open_to_write
    self.fp.write(zinfo.FileHeader(zip64))
  File "/usr/lib64/python3.7/zipfile.py", line 442, in FileHeader
    filename, flag_bits = self._encodeFilenameFlags()
  File "/usr/lib64/python3.7/zipfile.py", line 454, in _encodeFilenameFlags
    return self.filename.encode('utf-8'), self.flag_bits | 0x800
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcfc' in position 95: surrogates not allowed

Обновление:

Я пробовал некоторые решения, которые, казалось, работалидля некоторых по размещенной ссылке.Вот что я получил:
с ziph.write(filepath.encode('utf8','surrogateescape').decode('ISO-8859-1')) Я получил:

Traceback (most recent call last):
  File "run.py", line 41, in <module>
    zipdir(path, zipf)
  File "run.py", line 16, in zipdir
    ziph.write(filepath.encode('utf8','surrogateescape').decode('ISO-8859-1'))
  File "/usr/lib64/python3.7/zipfile.py", line 1713, in write
    zinfo = ZipInfo.from_file(filename, arcname)
  File "/usr/lib64/python3.7/zipfile.py", line 506, in from_file
    st = os.stat(filename)
FileNotFoundError: [Errno 2] No such file or directory: '/some/path/to/documents/DIS_Broschüre_DE.pdf'

Итак, кодирование / декодирование вернуло то, что не может быть найдено в файловой системе.

Другой вариант: ziph.write(filepath.encode('utf8','surrogateescape').decode('utf-8')) получил меня

Traceback (most recent call last):
  File "run.py", line 41, in <module>
    zipdir(path, zipf)
  File "run.py", line 16, in zipdir
    ziph.write(filepath.encode('utf8','surrogateescape').decode('utf-8'))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 96: invalid start byte

1 Ответ

1 голос
/ 29 сентября 2019

Хорошо.Я нашел проблему.Файлы в квесте не были теми, о которых я думал.Обычная умлаус работает нормально.Каким-то образом имена файлов были на самом деле повреждены.как это:

ls в одном из каталогов дает:
2e_geh�usetechnologie_flyer_qrcode.pdf

Автозаполнение командной строки дает мне:
2e_geh$'\344'usetechnologie_flyer_qrcode.pdf

Поскольку это файлы, которые были загружены через веб-интерфейс, я могу только представить, что они сделаны в Windows или другой ОС, отличной от UNIX, и веб-сервер не может их обработать.

В других загруженных файлах были правильные умлауты.Я не уверен, что там произошло, но я рад, что виноваты не Python или Linux FS.

Спасибо за все советы.

...