• python之多进程记录


    # -*- coding:utf-8 -*-
    #多进程
    import time
    import requests
    import multiprocessing
    from multiprocessing import Pool
    from bs4 import BeautifulSoup
    
    
    def job(url,header):
        r = requests.get(url,headers = header)
        content = r.text
        soup = BeautifulSoup(content,'html.parser')
        item = soup.select(".item")
        for i in item:
            print(i.select('.title')[0].text)
    if __name__ == "__main__":
        MAX_WOKER_NUM = multiprocessing.cpu_count()
        t1 = time.time()
        urls = ['https://movie.douban.com/top250?start={}&filter='.format(i) for i in range(0, 226, 25)]
        header = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ("
                          "KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
        }
        p = Pool(MAX_WOKER_NUM)
        for url in urls:
            #apply_async是异步非阻塞式,不用等待当前进程执行完毕,随时跟进操作系统调度来进行进程切换,
            # 即多个进程并行执行,提高程序的执行效率
            p.apply_async(job, args=(url,header))
        p.close()
        p.join()
        print("耗时:", time.time() - t1)

    上面的例子是爬取豆瓣Top250的电影名字总的耗时,其中涉及到了多进程的知识,在理解代码的过程中,查看了较多的资料,现在将所查看的一些资料记录下来。

    (1)p.apply_async()和p.apply()的区别。

    apply()的工作方式:阻塞主线程,并且一个一个按顺序执行子进程,等到全部子进程全部执行完毕后,继续执行apply()后面主进程的代码;

    apply_asaync()的工作方式:非阻塞异步的,它不会等待子进程执行完毕,主进程会继续执行,它会根据系统调度来进行进程切换;

    可根据代码的执行结果来进行理解,先看下apply().

    # -*- coding:utf-8 -*-
    import time
    import multiprocessing
    
    def doIt(num):
        print("Process num is : %s" % num)
        time.sleep(1)
        print('process  %s end' % num)
    
    if __name__ == '__main__':
        print('mainProcess start')
        #记录一下开始执行的时间
        start_time = time.time()
        #创建三个子进程
        pool = multiprocessing.Pool(3)
        print('Child start')
        for i in range(3):
            pool.apply(doIt,[i])
            #pool.apply_async(doIt,[i])print('mainProcess done time:%s s' % (time.time() - start_time))

    执行结果:

     从执行结果可以看出,主进程开始执行后,创建的3个子进程也开始执行,当三个子进程按顺序执行完毕后,,主进程接着执行后续的代码。

    当将apply()替换成apply_async()后,执行结果如下:

     从结果可以看出,主程序没有被阻塞,但子程序看起来好像没有被执行。这是因为进程的切换是操作系统控制的,首先运行的是主程序,我们都知道,CPU运行的很快,快到还没等系统调度到子线程,主线程就已经执行完毕了,并且推出程序了,所以子程序没有被运行。这样,当然不是我们所希望的,我们在程序中加上join()就可以解决问题了,如下:

    # -*- coding:utf-8 -*-
    import time
    import multiprocessing
    
    def doIt(num):
        print("Process num is : %s" % num)
        time.sleep(1)
        print('process  %s end' % num)
    
    if __name__ == '__main__':
        print('mainProcess start')
        #记录一下开始执行的时间
        start_time = time.time()
        #创建三个子进程
        pool = multiprocessing.Pool(3)
        print('Child start')
        for i in range(3):
            # pool.apply(doIt,[i])
            pool.apply_async(doIt,[i])
        pool.close()
        pool.join()
        print('mainProcess done time:%s s' % (time.time() - start_time))

    运行结果:

     根据结果可以看出,即使使用了非阻塞主进程的apply_async(),子进程也运行了,同时可观察到子进程是按顺序交替执行的。CPU在运行第一个子进程的时候,还没等第一个子进程执行完毕,系统调度按顺序调度到了第二个子进程,以此类推,一直调度运行子进程,一个接一个的结束了子进程的运行,最后运行主进程。

    (2)上面join()是什么用作呢?

    join()作用:在进程中可以阻塞主进程的执行,直到等待子进程全部完成之后,才继续运行主进程后面的代码。

    (3)pool.apply_async(func=test,args=(var,),callback=bar)  #将参数var传递给函数test,并将test的返回结果作为参数传递给函数bar。

  • 相关阅读:
    Div+Css布局教程(-)CSS必备知识
    html表格设置
    wxAui Frame Management用法
    aui
    MySQL死锁
    InnoDB索引存储结构
    MySQL事务调优
    MySQL慢SQL语句常见诱因
    InnoDB的LRU淘汰策略
    InnoDB事务之redo log工作原理
  • 原文地址:https://www.cnblogs.com/python-kp/p/12125455.html
Copyright © 2020-2023  润新知