当前位置: 首页 > 知识库问答 >
问题:

python3.x - 这种多进程如何实现?

毛越
2023-06-03

我自己写了一个多进程下载网络大文件的程序:基本思路是多进程分块下载完后,再拼接文件。
这个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个答案

胡承悦
2023-06-03
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()
 类似资料: