• 进程


    一、解释什么是进程
      任务管理器:里面都是进程
      对于操作系统而言,一个任务就是一个进程

      进程是系统中程序执行和资源分配的基本单位,每个进程都有自己的数据段,代码段和堆栈段。
      数据段:存储数据
      代码段:存储代码
        堆:存储对象
        栈:存储普通变量
      两个特点:全局变量在多个进程之间不能共享
           多个进程在并行的时候,不会出现数据混乱
      进程的目的:实现多任务,提高我们的执行效率
      进程: 就是创建一个任务,让它去执行其他的功能
    二、单任务现象
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 from time import sleep
     5 
     6 
     7 def run():
     8     while True:
     9         print("sunck is a nice man")
    10         sleep(1.2)
    11 
    12 
    13 if __name__ == '__main__':
    14     while True:
    15         print("sunck is a good man")
    16         sleep(1)
    17 
    18 
    19     # 不会执行 run 方法,只有上面的while循环结束才可以执行
    20     # 要让这两个任务同时执行,就是多任务
    21     run()
    单任务现象

    三、启动进程实现多任务

    multiprocessing 库
    multiple: adj.数量多的;多种多样的;
    n.倍数;
    processing: v.处理;加工;
    n.过程;加工处理;处置;进行;
    adj.经过特殊加工的;(用化学方法等)处理过的;

    在linux下可以使用C语言的方法fork实现多进程,但是它不支持window,
    但是这个三方库multiprocessing库是一个跨平台版本的多进程模块
    提供了一个Process类来代表一个进程对象
    所以我们要使用多进程就要引入multiprocessing库
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import os
     5 from time import sleep
     6 
     7 from multiprocessing import Process
     8 
     9 
    10 # 子进程需要执行的代码
    11 def run(adj):
    12     # os.getpid() 获取当前进程ID号
    13     # os.getppid() 获取当前进程的父进程ID号
    14     while True:
    15         print("sunck is a %s man--%s--%s"%(adj, os.getpid(),os.getppid()))
    16         sleep(1.2)
    17 
    18 
    19 if __name__ == '__main__':
    20     print("主(父)进程启动")
    21     # os.getpid() 获取当前父进程ID号
    22     print(os.getpid())
    23 
    24     # 创建一个子进程(在父进程下创建一个进程,故称为该进程的子进程)
    25     p = Process(target=run, args=("nice",))
    26     # target:说明 该子进程要执行的任务、代码、函数
    27     # args:可以给target的函数传参数,是一个元组类型,单个参数要加逗号,
    28 
    29     # 启动进程
    30     p.start()
    31 
    32     while True:
    33         print("sunck is a good man")
    34         sleep(1)
    启动进程实现多任务

    四、父子进程的先后顺序

      使用join(),让父进程等待子进程执行完毕,再执行。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 from multiprocessing import Process
     5 from time import sleep
     6 
     7 def run(args):
     8     print("子进程启动")
     9     sleep(3)
    10     print("子进程结束")
    11 
    12 if __name__ == '__main__':
    13     print("主(父)进程启动")
    14 
    15     p = Process(target=run, args=("nice",))
    16     p.start()
    17 
    18     # 父进程的结束不能影响子进程,让父进程等待子进程,再执行父进程
    19     p.join()
    20 
    21     print("父进程结束")
    父子进程的先后执行顺序

    五、全局变量在多个子进程之间不能共享

      因为每个进程都会有自己独立的数据段,代码段,和堆栈段。

      每次创建新的进程的时候,该进程就会将全局变量做一个属于自己的备份。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 from multiprocessing import Process
     5 from time import sleep
     6 
     7 NUM = 100
     8 
     9 
    10 def run():
    11     print("子进程开始")
    12     global NUM
    13     NUM += 1
    14     print(NUM)
    15     print("子进程结束")
    16 
    17 
    18 if __name__ == '__main__':
    19     print("父进程开始")
    20     
    21     p = Process(target=run)
    22     p.start()
    23     p.join()
    24     
    25     print(NUM)
    26     # 在子进程中修改全局变量对父进程中的全局变量没有影响
    27     # 为什么没影响呢?因为他在创建子进程时,对全局变量做了一个备份,父进程中的与子进程中的
    28     # NUM是两个完全不同的变量
    29     print("父进程结束--%d" % NUM)
    全局变量在多个进程中不能共享

    六、启动大量子进程(进程池)

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import os
     5 import time
     6 import random
     7 
     8 # from multiprocessing import Process
     9 # 为了对多个进程好管理,使用进程池
    10 from multiprocessing import Pool
    11 
    12 
    13 def run(name):
    14     print('子进程%s启动--%s' % (name, os.getpid()))
    15     strat = time.time()
    16     time.sleep(random.choice([1, 2, 3]))
    17     end = time.time()
    18     print('子进程%s结束--%s--耗时%.2f' % (name, os.getpid(), end-strat))
    19 
    20 
    21 if __name__ == '__main__':
    22     print('父进程启动')
    23 
    24     # 创建多个进程
    25     # 进程池
    26     # 4:表示可以同时执行的进程数量
    27     # 参数可以写,也可以不写,不写pool默认大小是CPU核心数
    28     pp = Pool(4)
    29 
    30     # 创建进程,创建的进程数要大于CPU核心数,这样才能体验到多进程的效果
    31     # 这里因为进程都是干一样的活,所以使用for循环创建进程
    32     # 子进程的执行顺序是没有顺序的。
    33     for i in range(5):
    34         # 创建进程,放进进程池,统一管理
    35         pp.apply_async(run, args=(i,))
    36 
    37     '''
    38     如果每个进程干的活不一样,那就单独创建每一个进程,不要写for循环。
    39     例:
    40     pp.apply_async(func1, agrs=())
    41     pp.apply_async(func2, agrs=())
    42     pp.apply_async(func3, agrs=())
    43     pp.apply_async(func4, agrs=())
    44     pp.apply_async(func5, agrs=())
    45     '''
    46 
    47     # 在调用join之前,必须先调用close,并且在调用close之后,就不能再继续添加新的进程了
    48     pp.close()
    49     # 进程池对象调用的join,会等待进程池中的所有的子进程结束完毕,再去执行父进程。
    50     pp.join()
    51 
    52     print("父进程结束")
    53 
    54 '''
    55 运行结果:  这里进程看似0,1,2,3启动的,实际上,进程启动是没有顺序的。
    56 父进程启动
    57 子进程0启动--5251
    58 子进程1启动--5252
    59 子进程2启动--5253
    60 子进程3启动--5254
    61 子进程2结束--5253--耗时1.00
    62 子进程0结束--5251--耗时1.00
    63 子进程4启动--5253
    64 子进程3结束--5254--耗时1.00
    65 子进程1结束--5252--耗时2.00
    66 子进程4结束--5253--耗时3.00
    67 父进程结束
    68 '''
    启动大量子进程(进程池)

    七、二次封装

      继承第三方的某各类,然后重写它的 init 方法,run 方法

     1 #二次封装的文件名,一般是:自己的名字+第三方库的名称
     2 
     3 import os
     4 import time
     5 from multiprocessing import Process
     6 
     7 
     8 class SunckProcess(Process):
     9     def __init__(self, name):
    10         super().__init__()
    11         self.name = name
    12 
    13     def run(self):
    14         super().run()
    15         print('子进程(%s-%s)启动' % (self.name, os.getpid()))
    16         # 子进程的功能
    17         time.sleep(3)
    18         print('子进程(%s-%s)结束' % (self.name, os.getpid()))
    sunckProcess
     1 from sunckProcess import SunckProcess
     2 
     3 
     4 if __name__ == '__main__':
     5     print('父进程启动')
     6 
     7     # 创建子进程
     8     p = SunckProcess('test')
     9     # 在这里不要调用进程里面的run方法,调用它的start就会自动调用进程对象的run方法
    10     p.start()
    11     p.join()
    12 
    13     print("父进程结束")
    二次封装

    八、进程间通信

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import os
     5 import time
     6 from multiprocessing import Process
     7 from multiprocessing import Queue
     8 
     9 
    10 def write(args):
    11     print('启动写子进程%s' % (os.getpid()))
    12     for letter in ['a', 'b', 'c', 'd']:
    13         q.put(letter)
    14         time.sleep(1)
    15     print('结束写子进程%s' % (os.getpid()))
    16 
    17 
    18 def read(args):
    19     print('启动读子进程%s' % (os.getpid()))
    20     while True:
    21         value = q.get(True)
    22         print('value = ' + value)
    23     print('结束读子进程%s' % (os.getpid()))
    24 
    25 
    26 if __name__ == '__main__':
    27     # 父进程创建队列,并传递给子进程
    28     q = Queue()
    29     pw = Process(target=write, args=(q,))
    30     pr = Process(target=read, args=(q,))
    31 
    32     pw.start()
    33     pr.start()
    34     #
    35     pw.join()
    36     # pr进程里面是个死循环,无法等待其结束,只能强行结束
    37     pr.terminate()
    38 
    39     print('父进程结束')
    进程间通信
     
    愿你多向优秀的人学习; 愿你不怕麻烦,勤做总结; 愿你每天都有意义; 愿你不负年华; 愿你…… 愿你…… 愿你…… 愿你一生都快乐!
  • 相关阅读:
    学习笔记datatablexml转换
    立即执行函数
    MySQL基操—1.Linux下安装(CentOS6/7yum、rpm、tar)
    Linux1.11.shell(环境变量配置文件)
    三国HR评估报告
    毕业5年后拉开差距的原因
    职业的选择
    WPF图片的缩放节省内存
    .asmx支持post请求或者get请求调用
    ionic3遇到的刷新页面服务器关闭的问题
  • 原文地址:https://www.cnblogs.com/linpd/p/10055606.html
Copyright © 2020-2023  润新知