我自己写了一个多进程下载网络大文件的程序:基本思路是多进程分块下载完后,再拼接文件。
这个url的大文件被分割成20个部分,开启了4个进程下载。
vim mpdown.py
import requests
n = 20
url = "https://laotzu.ftp.acc.umu.se/debian-cd/current/amd64/iso-cd/debian-11.7.0-amd64-netinst.iso"
response = requests.get(url, stream=True)
file_size = int(response.headers['content-length'])
a,b = divmod(file_size,n)
def range_down(i):
if i == n-1:
start = i * a
end = file_size - 1
else:
start = i * a
end = (i+1)*a - 1
dst = '/tmp/tmp' + str(i) + '.part'
header = {"Range": "bytes={}-{}".format(start,end)}
req = requests.get(url, headers=header)
with(open(dst, 'ab')) as f:
f.write(req.content)
def merge():
f = open('/tmp/result','ab+')
for i in range(0,n):
fname = '/tmp/tmp' + str(i) + '.part'
ftmp = open(fname,'rb')
f.write(ftmp.read())
ftmp.close()
f.close()
if __name__ == '__main__':
from multiprocessing import Pool
pool = Pool(processes = 4)
for i in range(0,n):
pool.apply_async(range_down,args=(i,))
pool.close()
pool.join()
merge()
测试运行: python3 mpdown.py #速度比单进程快50%以上。
现在我有点不满意这个多进程下载,拼接文件(merge)是在全部下载完成后,再拼接,我想这个拼接动作也修改成多进程并行的,边下载边拼接。
由于下载是多进程的,各进程存在一定的竞争
/tmp/tmp0.part,/tmp/tmp1.part,/tmp/tmp2.part,/tmp/tmp3.part,/tmp/tmp4.part,这些文件不会完全按照顺序产生,考虑使用生产者消费者模型,生产者下载文件,消费者拼接文件,但是如何解决文件顺序在下载过程中不一致的问题?
让拼接文件这个过程也动态起来。