python多进程multiprocessing

Python中的线程手全局锁的影响,线程受限于某个cpu上,但是呢,多进程模式,不手此影响。多线程,省资源。多进程有点浪费资源,但是能利用上多核的性能。

记录一下,python中的多进程使用方式。另外一种多进程方式concurrent的库。

资料

示例

多进程下载

对于标记的核心代码,解释如下,进程数,根据自己电脑的cpu的情况而定,不能太多,因为进程切换也需要耗时间的。重要:进程池,定义n个进程,但是,实际上,可以比它多,也可以比它少。

举例:如下,定义了4个进程,但是,pool.apply_async处,就调用1次,也是允许的。这样,最终,只会有一个进程。如果超过了它,比如n个进程,那么每次任务结束的时候,进程会执行新的任务。

下面seg_down,实际上是因为每次下载的任务太小了,故封装成一个大一点的任务量。这样,workers的变量也会少一点。

#coding=utf-8
import requests
from time import sleep
import multiprocessing as mp
import sys
"""
带有失败重试的下载功能代码
"""
def get_dipian(uid):
    for i in range(10):
        try:
            resp = requests.get(url,headers=headers,stream=True)
            break
        except:
            print('网络可能超时 id -- %s'%uid )
            sleep(i)
        if i == 9:
            print('当前任务反复获取不到,被忽略 id -- %s'%uid)
            return False
    return resp.status_code == 200

"""
仅仅是合并一下任务,避免任务太多
"""
def seg_down(k):
    result = []
    for i in range(k*10000,min((k+1)*10000,pow(16,5))):
        uid = '%05x'.upper()%i
        if get_dipian(uid):
            result.append(uid)
            print(uid)
    print('当前进度:%d 已完成'%(k))
    return result

"""
多进程的方式,提高下载的并发速度
"""
def main():
    result = []
    assert len(sys.argv)  == 3
    start_n = sys.argv[1]
    end_n =  sys.argv[2]
    assert start_n.isnumeric()
    assert end_n.isnumeric()
    start_n = int(start_n)
    end_n = int(end_n)
    
    # 多进程的核心代码
    pool = mp.Pool(4)
    workers = [pool.apply_async(seg_down,[k]) for k in range(start_n,end_n)]
    pool.close()
    pool.join()
    result = [worker.get() for worker in workers]
    
    with open('dipian_ids_%s.txt'%image_day,'a') as fo:
        fo.write('\n'.join(['%s'%x for x in result]))
    
if __name__ == '__main__':
    main()