首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Twistd中不阻塞地压缩文件。

在Twistd中不阻塞地压缩文件。
EN

Stack Overflow用户
提问于 2018-05-28 15:38:02
回答 2查看 66关注 0票数 1

有没有一种方法可以在不阻塞扭曲的情况下压缩文件?

代码语言:javascript
复制
import zipfile
from twisted.internet import defer
from twisted.internet import reactor

def zip_files(file_list, path, output_Zip):
    zip_handle = zipfile.ZipFile(output_zip,  mode='w', allowZip64=True)
    try:
        for i in file_list:
            zip_handle.write(i)
        zip_handle.close()
        return True
    except Exception as e:
        return False
def print_zip(res):
    print res
    return res


file_list = ['path_to_file1','path_to_file2']
output_path = 'full_path_to_output_zip'
d = defer.Deferred()
d.addCallback(lambda _: zip_files(file_list, output_path)
d.addCallback(print_zip)
zip_result = d
reactor.run()

到目前为止我有这个。虽然它确实工作,触发拉链过程导致扭曲阻塞和等待,直到初始的'zip作业‘完成。Id,而不是终止现有的'zip作业‘,并启动新的工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-28 18:16:46

可能是这样的,使用DeferredList of deferToThreads不阻止编写zip文件:

代码语言:javascript
复制
import zipfile
import logging
from twisted.internet import threads, defer
from twisted.internet import reactor

log = logging.getLogger()
log.addHandler(logging.StreamHandler())
log.setLevel(logging.INFO)


def zip_file(input_path, output_path):
    with zipfile.ZipFile(output_path,  mode='w', allowZip64=True) as zip_handle:
        zip_handle.write(input_path)


def log_failure(err):
    log.exception("error: %s", err)


def zip_file_and_catch_error(input_path, output_path):
    d = threads.deferToThread(zip_file, input_path, output_path)
    d.addErrback(log_failure)
    return d


def main():
    input_paths = ['path_to_file1','path_to_file2']
    output_paths = ['path_out1','path_out2']
    assert len(input_paths) == len(output_paths)
    dl = defer.DeferredList([zip_file_and_catch_error(input_path, output_path) 
                             for input_path, output_path in zip(input_paths, output_paths)])
    dl.addCallback(lambda result: log.info("result: %s", result))
    dl.addBoth(lambda _: reactor.callLater(0, reactor.stop))
    reactor.run()


if __name__ == "__main__":
    main()
票数 1
EN

Stack Overflow用户

发布于 2018-05-28 20:36:33

代码语言:javascript
复制
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修饰并返回一个“延迟”),如果有必要,可以很容易地访问它。成功和错误回调将被处理(通过addCallback/addErrback),更新这些函数以满足您的需要。最后,ZipFile对象(从主函数传递到close_zip_obj() )一旦完成拉链操作就会关闭。这应该可以相当快地处理大量中等大小的文件。对于大型文件,您应该可以使用原始代码在deferToThread中执行任务。

然而,您所作的评论非常含糊:

Id,而不是终止现有的'zip作业‘,并启动新的工作。

这假设如果您处于压缩的中间,您希望停止当前的压缩并启动另一个压缩。使用deferToThread或任何线程方法,在线程之间传递标志、设置/未设置锁以及与其他线程同步变得非常繁琐。如果您决定使用线程,请记住这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50569692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档