这种多进程如何实现?
我自己写了一个多进程下载网络大文件的程序:基本思路是多进程分块下载完后,再拼接文件。这个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,这些文件不会完全按照顺序产生,考虑使用生产者消费者模型,生产者下载文件,消费者拼接文件,但是如何解决文件顺序在下载过程中不一致的问题?让拼接文件这个过程也动态起来。
回复
1个回答
test
2024-07-02
from multiprocessing import Process, Queue
def downloader(queue, i):
# 下载文件
# ...
queue.put(i)
def merger(queue):
next_to_merge = 0
while True:
i = queue.get()
if i == next_to_merge:
# 拼接文件
# ...
next_to_merge += 1
else:
queue.put(i)
if __name__ == '__main__':
queue = Queue()
for i in range(n):
Process(target=downloader, args=(queue, i)).start()
Process(target=merger, args=(queue,)).start()
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容