这种多进程如何实现?

作者站长头像
站长
· 阅读数 7

我自己写了一个多进程下载网络大文件的程序:基本思路是多进程分块下载完后,再拼接文件。这个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个回答
avatar
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()
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容