multiprocessing模块就是跨平台版本的多进程模块,它提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。

多进程的创建

多进程的创建和多线程的创建差不多

import multiprocessing
from time import sleep


def dog():
    for i in range(5):
        print('www%d'%i)
        sleep(1.5)


def cat():
    for i in range(5):
        print('mmm%d'%i)
        sleep(1)


if __name__ == '__main__':
    t1 = multiprocessing.Process(target=dog)
    t2 = multiprocessing.Process(target=cat)
    t1.start()
    t2.start()

只是把threading.Thread换成multiprocessing.Process


进程与线程的区别

  • 线程执行开销小,但不利于资源的管理和保护;而进程相反
  • 线程不能够独立执行,必须依存在进程中
  • 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性较高
  • 进程在执行过程中拥有独立的内存单元,而多线程共享内存,从而极大的提高了程序的运行效率

进程间通信

  1. 可以使用socket通信来进行进程间通信
  2. 通过写文件和读文件来进行进程间通信

    3. 通过队列(Queue)来进行进程间通信(重点)

    队列的特点是先进先出,这样我们就可以在一个进程中往队列中写东西,另一个进程从队列中读取数据,这样就实现了进程通信。

import multiprocessing
from queue import Empty
from time import sleep


def download(q):
    # 模拟下载数据
    for i in range(10):
        q.put(i)
        sleep(1)


def analysis(q):
    # 模拟分析数据
    analysis_data = list()
    while True:
        try:
            data = q.get(timeout=2)
        except Empty:
            break
        analysis_data.append(data)
        print(analysis_data)


def main():
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=download, args=(q,))
    p2 = multiprocessing.Process(target=analysis, args=(q,))
    p1.start()
    p2.start()


if __name__ == '__main__':
    main()

这里的案例一个进程模拟下载数据,一个进程模拟分析数据,用队列进行通信


进程池

如果要创建子程序很多时,就可以考虑创建一个进程池

初始化进程池Pool时,可以指定一个最大进程数,当有新的请求提交到Pool时,如果还没有满,那么就会创建一个新的进程来执行请求,如果Pool中满了,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。

  • 在进程池中如果代码出现异常不会报错

例如我之前写的爬虫改进版:

def main():
    q = multiprocessing.Manager().Queue()   # 创建进程池内Queue消息队列通信
    p = multiprocessing.Process(target=insert_data,args=(q,))
    p.start()
    po = multiprocessing.Pool(3)
    for i in range(1,11):
        po.apply_async(jd_spider,(q,i))
    po.close()
    po.join()

这里有一个,在进程池中进行队列通信是定义队列要用multiprocessing.Manager().Queue()

最后修改:2020 年 07 月 22 日
如果觉得我的文章对你有用,请随意赞赏