在python中使用多线程下载文件

2024-06-26 14:59:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试在pythoncgi中使用多线程将多个文件(ard25k)放入一个zip文件中。我已经写了下面的脚本,但不知何故,我得到的响应内容长度为0,并且响应中没有数据。这是我第一次在python中使用多线程。密码里有什么我遗漏的吗。输出是否在数据发布之前就打印出来了?在

任何帮助都将不胜感激。在

这是我的代码:

b = StringIO()
z = zipfile.ZipFile(b, 'w', zipfile.ZIP_DEFLATED)

def read_file(link):
    fname = link.split('/')
    fname = fname[-1]
    z.write(link, fname)

if __name__ == '__main__':
    form = cgi.FieldStorage()
    fileLinks = form.getvalue("fileLink")

    p = Pool(10)
    p.map(read_file, fileLinks)
    p.close()
    p.join()
    z.close()
    zipFilename = "DataFiles-" + str(time.time()) + ".zip"   
    length = b.tell()
    sys.stdout.write(
        HEADERS % ('application/zip', zipFilename, zipFilename, length)
    )
    b.seek(0)
    sys.stdout.write(b.read())
    b.close()

同一代码的顺序版本:

^{pr2}$

Tags: 文件数据代码formclosereadtimelink
1条回答
网友
1楼 · 发布于 2024-06-26 14:59:02

问题应该是ZipFile.write()(通常是ZipFile)不是线程安全的。在

您必须以某种方式序列化对zip文件的线程访问。这是一种方法(在Python 3中):

ziplock = threading.Lock()

def read_file(link):
    fname = link.split('/')
    fname = fname[-1]
    with ziplock:
        z.write(link, fname)

这样做应该没有什么好处,因为锁实际上是在序列化zip文件的创建。在

此版本可以实现一些并行化,即在将文件内容添加到zip文件之前读取文件内容:

^{pr2}$

但是,如果这些文件驻留在同一个文件系统上,那么读操作很可能会像操作系统序列化了它们一样。在

因为它是文件,所以并行化的可能目标是进程中CPU受限的部分,即压缩,而对于zip格式,这似乎是不可能的(因为zip文件的行为类似于一个目录,所以每个write()必须保持状态,以便在close()上生成完整的存档)。在

如果您可以使用不同的压缩格式,那么并行化将在没有锁的情况下工作,使用gizp进行压缩,tartarfile)作为存档格式,因为每个文件都可以并行读取和压缩,并且只有tar连接将按顺序进行(即.tar.gz.tgz存档格式)。在

相关问题 更多 >