我使用的是PyCurl,范围为http的标头和Python线程,因此,如果我需要下载1 gb文件并想使用例如与服务器的5条连接来加快处理速度,我将1 gb分为五个部分,并创建五个线程,每个线程下载1/5,然后将1/5保存到“ .part”文件中,当5个线程全部完成并下载其1/5文件时,我只需加入所有部分并重新创建1 GB档案。
我的问题是:我如何以相同的5个块下载文件,而不是将每个块保存到临时文件中,然后将所有文件都合并到原始文件中,只需下载5个部分并将这些部分保存到直接一个1gb文件?这可能吗?
答案 0 :(得分:2)
因此,正如我们在评论中讨论的那样,您不能真的做您想做的事情。不过,我有几个想法可能会对您有所帮助。
如果您知道要下载的文件大小,则可以创建所需大小的文件,并用下载的字节覆盖。
with open("some_file_name", "wb") as f:
f.truncate(some_size)
或
with open("some_file_name", "wb") as f:
f.seek(some_size - 1)
f.write('\0')
请注意,如果指定的大小超过文件的当前大小,则结果取决于平台:可能包括文件可能保持不变,增大为指定的大小(好像是零填充的)或增大为指定的大小大小以及未定义的新内容。
因此,在下载部分时,您可以使用来覆盖特定的字节块
with open("some_file_name", "r+b") as f:
f.seek(offset)
f.write(data_chunk)
确定您愿意使用多少内存,一次只能下载一定数量的部件。
示例:如果您决定只使用1GB,并且要下载250 MB的大文件
写入临时文件(如您在原始问题中提到的那样),但将其保存在用户可能看不到它们的位置,例如系统的temp目录或程序创建的隐藏目录中
答案 1 :(得分:1)
至少在Unix / Linux系统上,您应该能够轻松地做到这一点。关键是您应该在线程1中创建一次文件,然后将其打开以进行写入。然后,您需要再重新打开个文件N次以上(也用于写操作,但绝不用于附加操作),以便为每个要使用的线程获得一个独立的文件描述符。
接下来,使用其自己的文件描述符将每个线程lseek
移至文件中的适当起始位置,然后从服务器接收到后,它就可以开始将大块写入文件中。 (只要您使用的是二进制I / O,您也应该能够使用标准的python文件对象及其seek
方法。)
之所以起作用,是因为每个文件描述符都有一个独立的文件指针,并且在所有的UNIX系统上,文件指针应在编写时自动前进。而且,文件中没有空隙也没有问题;操作系统应该可以处理。
IOW,用于具有5个线程的1GB文件:
thread 1, fd 1, position 0 (writing through 200MB-1)
thread 2, fd 2, position 200MB (through 400MB-1)
...
thread 5, fd 5, position 800MB (through 1GB-1)
python中的线程代码(假设您已经在主线程中创建了文件)可以很简单:
with open("the_file", "r+b") as myfile: # open for update
myfile.seek(my_starting_pos)
while ...:
next_chunk = recv_from_server()
myfile.write(next_chunk)