Является ли python zipfile поточно-ориентированным? - PullRequest
7 голосов
/ 08 февраля 2012

В проекте django мне нужно создать несколько файлов PDF для объектов в БД.Поскольку создание каждого файла занимает несколько секунд, я использую celery для асинхронного запуска задач.

Проблема в том, что мне нужно добавить каждый файл в zip-архив.Я планировал использовать модуль python zipfile, но разные задачи могут выполняться в разных потоках, и мне интересно, что произойдет, если две задачи попытаются добавить файл в архив одновременно.

Является лиследующий поток кода безопасен или нет?Я не могу найти никакой ценной информации в официальном документе Python.

try:
    zippath = os.path.join(pdf_directory, 'archive.zip')
    zipfile = ZipFile(zippath, 'a')
    zipfile.write(pdf_fullname)
finally:
    zipfile.close()

Примечание: это работает под Python 2.6

Ответы [ 3 ]

5 голосов
/ 08 февраля 2012

Нет, это не потокобезопасно в этом смысле. Если вы добавляете один и тот же zip-файл, вам понадобится блокировка, иначе содержимое файла может быть зашифровано. Если вы добавляете файлы в разные zip-файлы, используя отдельные ZipFile() объекты, тогда все в порядке.

1 голос
/ 06 мая 2018

Python 3.5.5 делает запись в ZipFile и чтение нескольких потоков ZipExtFiles безопасными: https://docs.python.org/3.5/whatsnew/changelog.html#id93

Насколько я могу судить, изменение не было перенесено в Python 2.7.

Обновление: после изучения кода и некоторого тестирования становится очевидно, что блокировка все еще не полностью реализована.Он корректно работает только для writestr и не работает для open и write.

0 голосов
/ 29 июля 2015

Несмотря на то, что этот вопрос старый, он все еще высоко отражен в результатах поиска в Google, поэтому я просто хочу вмешаться, чтобы сказать, что я заметил, что на Python 3.4 64bit в Windows zz-файл lzma является поточно-ориентированным; все остальные терпят неудачу.

with zipfile.ZipFile("test.zip", "w", zipfile.ZIP_LZMA) as zip:
    #do stuff in threads

Обратите внимание, что вы не можете связать один и тот же файл с несколькими экземплярами zipfile.ZipFile, вместо этого вы должны использовать один и тот же файл во всех потоках; здесь это переменная с именем zip.

В моем случае я получаю около 80-90% использования ЦП на 8 ядрах и SSD, что приятно.

...