import zipfile
from twisted.internet import defer, reactor
def main():
file_list = ['path_to_file1','path_to_file2']
output_path = 'full_path_to_output.zip'
zip_obj = zipfile.ZipFile(output_path, mode='w', allowZip64=True)
d = zip_files(zip_obj, file_list)
d.addCallback(handle_success)
d.addErrback(handle_error)
d.addBoth(close_zip_obj, zip_obj = zip_obj)
@defer.inlineCallbacks
def zip_files(zip_obj, file_list):
for item in file_list:
yield zip_obj.write(item)
# handle "interrupts" here
def handle_success(ignore):
print('Done zipping')
def handle_error(failure):
print('Error: {0}'.format(failure.value))
def close_zip_obj(ignore, zip_obj):
print('Closing zip object')
zip_obj.close()
main()
reactor.run()
Я старался, чтобы мой пример был простым, чтобы новички в Twisted не запутались.Объект ZipFile
создается снаружи и передается в zip_files()
(который теперь отмечен @inlineCallbacks
и возвращает 'Deferred'), таким образом, к нему можно легко получить доступ при необходимости.Обработанные вызовы и вызовы ошибок (через addCallback/addErrback
) обновляют эти функции в соответствии с вашими потребностями.Наконец, объект ZipFile
, который передается в close_zip_obj()
из главной функции, закрывается после завершения архивирования.Это должно обрабатывать множество файлов среднего размера довольно быстро.Для больших файлов вы «должны» быть в порядке, выполняя задачу в deferToThread
с использованием вашего исходного кода.
Однако вы сделали очень размытый комментарий:
Я бы предпочел прекратить существующее «задание zip» и запустить новое.
Предполагается, что если вы находитесь в середине zip, вы хотите остановить текущий zipи начать еще один.С deferToThread
или любым многопоточным подходом становится утомительным передавать флаги между потоками, устанавливать / снимать блокировки и синхронизироваться с другими потоками.Просто имейте это в виду, если решите использовать нити.