6.爬虫必备基础知识(高效编程之多进程)

高效编程

一、多任务原理

  • 概念

    现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统

  • 什么叫多任务?

    就是操作系统可以同时运行多个任务

  • 单核CPU实现多任务原理

    操作系统轮流让各个任务交替执行,QQ执行2us(微秒),切换到微信,在执行2us,再切换到陌陌,执行2us……。表面是看,每个任务反复执行下去,但是CPU调度执行速度太快了,导致我们感觉就像所有任务都在同时执行一样

    截屏2020-01-1314.49.04

  • 多核CPU实现多任务原理

    ​ 真正的秉性执行多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行

    截屏2020-01-1314.48.20

  • 并发与并行

    • 并发

      CPU调度执行速度太快了,看上去一起执行,任务数多于CPU核心数

    • 并行

      真正一起执行,任务数小于等于CPU核心数

    • 并发是逻辑上的同时发生,并行更多是侧重于物理上的同时发生。

  • 实现多任务的方式

    • 多进程模式

      启动多个进程,每个进程虽然只有一个线程,但是多个进程可以一起执行多个任务

    • 多线程模式

      启动一个进程,在一个进程的内部启动多个线程,这样多个线程也可以一起执行多个任务

    • 多进程+多线程

      启动多个进程,每个进程再启动多个线程

    • 协程

    • 多进程+协程

二、进程

1、概念

  • 什么是进程?

    是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

  • 对于操作系统

    一个任务就是一个进程。比方说打开浏览器就是启动一个浏览器的进程,在打开一个记事本就启动一个记事本进程,如果打开两个记事本就启动两个记事本进程

2、使用进程

  • 单进程现象

    需要等待代码执行完后再执行下一段代码

    import time
    
    def run1():
        while 1:
            print("lucky is a good man")
            time.sleep(1)
    
    def run2():
        while 1:
            print("lucky is a nice man")
            time.sleep(1)
    
    if __name__ == "__main__":
        run1()
        # 不会执行run2()函数,只有上面的run1()结束才能执行run2()
        run2()
    
  • 启动进程实现多任务

    • multiprocessing模块

      跨平台的多进程模块,提供了一个Process类用来示例化一个进程对象

    • Process类

      作用:创建进程(子进程)

    • __name__

      这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。

      参数 说明
      target 指定进程执行的任务
      args 给进程函数传递的参数,是一个元组

      注意:此时进程被创建,但是不会启动进程执行

    • 启动进程实现多任务

      from multiprocessing import Process

      创建子进程

      P = Process(target=run,args=(“nice”,),name=‘当前进程名称’)

      • target指定 子进程运行的函数

      • args 指定传递的参数 , 是元组类型

      • 启动进程:Process对象.start()

      获取进程信息

      • os.getpid() 获取当前进程id号
      • os.getppid() 获取当前进程的父进程id号
      • multiprocessing.current_process().name 获取当前进程名称

      父子进程的先后顺序

      • 默认 父进程的结束不能影响子进程 让父进程等待子进程结束再执行父进程

      • p.join() 阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。

      • 全局变量在过个进程中不能共享

        注意: 在子线程中修改全局变量时对父进程中的全局变量没有影响

    • 示例代码

      import time
      
      from multiprocessing import Process
      
      def run1(name):
          while 1:
              print("%s is a good man"%name)
              time.sleep(1)
      
      def run2():
          while 1:
              print("lucky is a nice man")
              time.sleep(1)
      
      if __name__ == "__main__":
          # 程序启动时的进程称为主进程(父进程)
          
          # 创建进程并启动
          p = Process(target=run1, args=("lucky",))
          p.start()
      
          # 主进程执行run2()函数
          run2()
      
  • 主进程负责调度

    主进程主要做的是调度相关的工作,一般不负责具体业务逻辑

    import time
    from multiprocessing import Process
    
    def run1():
        for i in range(7):
            print("lucky is a good man")
            time.sleep(1)
    
    def run2(name, word):
        for i in range(5):
            print("%s is a %s man"%(name, word))
            time.sleep(1)
    
    if __name__ == "__main__":
        t1 = time.time()
    
        # 创建两个进程分别执行run1、run2
        p1 = Process(target=run1)
        p2 = Process(target=run2, args=("lucky", "cool"))
    
        # 启动两个进程
        p1.start()
        p2.start()
    
        # 查看耗时
        t2 = time.time()
        print("耗时:%.2f"%(t2-t1))
    
  • 父子进程的先后顺序

    主进程的结束不能影响子进程,所以可以等待子进程的结束再结束主进程,等待子进程结束,才能继续运行主进程

    p.join() 阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。

    import time
    from multiprocessing import Process
    
    def run1():
        for i in range(7):
            print("lucky is a good man")
            time.sleep(1)
    
    def run2(name, word):
        for i in range(5):
            print("%s is a %s man"%(name
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

歌颂平凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值