Python中的进程

来源:互联网 发布:杀毒软件知乎 编辑:程序博客网 时间:2024/06/04 19:19

Python中的进程

1、单任务和多任务

  • 单任务:一次做一件事件,前一件事情做完,才开始下一件事情
  • 多任务:同时做多件事情,多件事情可以同时处理。

2、单核CPU的多任务

  • 时间片:CPU执行时间分割成小段

3、并行和并发

  • 并行:m个任务在m个处理器运算核心上执行
  • 并发:m个任务在n个处理器运算核心上执行,m>n

4、程序和进程

  • 程序:存放代码的可执行文件,静态的
  • 进程:运行中的程序,进程需要相应的系统资源:内存、时间片、pid。动态的

5、fork

​ Python中的OS模块封装了常见的系统调用,可以使用OS模块中的fork()方法来创建新的进程

  • fork只能在linux/unix系统中使用,windows中是不可以的
  • 当程序执行os.fork()时,系统会创建出一个新的进程(子进程),然后复制父进程中的所有内容到子进程中。
  • 父进程、子进程都会从fork()函数中得到一个返回值。
    • 父进程,得到子进程的pid
    • 子进程,得到返回值0
import osdef main():    pid = os.fork()    if pid > 0:        print("父进程---Hello")    elif pid == 0:        print("子进程---world")if __name__ == "__main__":    main()

​ 运行结果:

父进程---Hello子进程---world

6、多进程中的全局变量

import osimport timenum = 10# 全局变量在多进程中,每个进程拥有的数据(包括全局变量)各有一份,是互不相关的# 在父进程中,我们通过global改变了全局变量num的值,但是在子进程中,还是之前没有改变的num的值def sing():    global num    for temp in range(3):        print("----sing--num:%d---pid:%d--ppid:%d" % (num, os.getpid(), os.getppid()))        num += 1        time.sleep(1)def dance():    for i in range(3):        print("------dance--num:%d--pid:%d,ppid:%d" % (num, os.getpid(), os.getppid()))        time.sleep(1)def main():    pid = os.fork()    if pid > 0:        sing()    elif pid == 0:        dance()if __name__ == "__main__":    main()

​ 运行结果:

----sing--num:10---pid:32922--ppid:20979------dance--num:10--pid:32927,ppid:32922----sing--num:11---pid:32922--ppid:20979------dance--num:10--pid:32927,ppid:32922----sing--num:12---pid:32922--ppid:20979------dance--num:10--pid:32927,ppid:32922

总结:

在多进程中,每个进程中有的数据(包括全局变量),各有一份,在父进程中通过global改变了全局变量,在子进程中全局变量还是之前的值,不会改变。

父进程、子进程执行的顺序是没有规律的,完全取决于操作系统的调度算法

7、getpid和getppid

  • os.getpid(): 获取当前进程的pid
  • os.getppid(): 获取当前进程父进程的pid,即ppid

8、使用Process创建多进程

​ 上面提到os.fork()不能在Windows下运行,那么既然说Python是一门跨平台的语言,那我们怎么在Windows平台下使用多进程呢?答案就是使用Process。

​ 使用Process创建多进程的流程:

  • 首先导入Process

    form multiprocessing import Process

  • 创建一个Process对象

    p = Process() # 参数等会结合Demo讲解

  • 启动进程

    p.start() # 进程不启动,没有pid,但是会有进程名

  • 结束进程

    p.terminate()

    p.join() # 导致父进程阻塞,等待子进程结束,并回收资源

  • 创建Process对象时,可传递的参数:

    p = Process(target=XXX, args=(元组), kwargs={key:value})

    target = XXX 指定的任务函数

    args = (元组) 、kwargs={key:value} 给任务函数传递的参数

  • 判断进程是否在运行了

    p.is_alive() # True表示在运行 False表示未运行

    Demo

    import osfrom multiprocessing import Processdef myTask():for i in range(5):    print("子进程进程:%d --------%d" % (os.getpid(), i))def main():print("父进程:%d" % os.getpid())# 创建一个进程p = Process(target=myTask)# 启动进程p.start()# 阻塞父进程,等待子进程结束,并回收哦资源p.join()if __name__ == '__main__':main()

9、Process语法结构

Process([group [, target [, name [, args [, kwargs]]]]])

  • target:表示这个进程实例所调用的对象

  • args:表示调用对象的位置参数元组

  • kwargs:表示 调用对象的关键字参数字典

  • name:为当前进程实例的别名

  • group:大多数情况下用不到

    Process类的常用方法:

  • is_alive():判断进程实例是否还咋执行

  • join(timeout):是否等待进程实例执行结束,或等待多少秒

  • start():启动进程实例(创建子进程)

  • run():如果没有给定target参数,对这个对象调用start()方法,就将执行对象中的run()方法

  • terminate():不管任务是否完成,立即终止

    Process类常用的属性:

  • name:当前进程实例别名,默认名为Process-N,N为从1开始递增的整数

  • pid:当前进程实例的Pid值

10、使用Process子类创建进程

​ 这就关系到了之前的面向对象中的继承,我们来写程序,来使用 Process的子类来创建进程。

​ Demo:

import osfrom multiprocessing import Processimport time"""    Process类本身也有__init__方法,这个子类相当于重写了这个方法    但是这样有一个问题,我们并没有完全的初始化一个Process类,所以就不能从这个类中继承一些方法和属性    最好的方法就是在__init__方法中奖继承类本身传递给Process.__init__方法,完成初始化操作"""class MyProcess(Process):    def __init__(self):        Process.__init__(self)    def run(self):        """要执行的任务代码写在run方法中"""        for i in range(5):            print("子进程:%d,正在运行。。。%d" % (os.getpid(), i))            time.sleep(1)def main():    print("父进程:%d,正在运行。。。" % os.getpid())    p = MyProcess()    p.start()    p.join()if __name__ == '__main__':    main()

​ 运行结果:

父进程:16836,正在运行。。。子进程:13432,正在运行。。。0子进程:13432,正在运行。。。1子进程:13432,正在运行。。。2子进程:13432,正在运行。。。3子进程:13432,正在运行。。。4
原创粉丝点击