zoukankan      html  css  js  c++  java
  • python第九篇:Python进程

    Python进程

    接下来我主要按照下图中思维导图上的关键点对进程和线程进行一个总结

    进程知识点总结:

     

    一、Python进程

    1.概念

    程序和进程:

    程序:是可执行文件,是静态的,占据磁盘空间,程序运行的时候会产生进程。

    进程:进程是一个动态的过程,占有计算机资源,有一定的生命周期。

    并行和并发:

    并行:多个任务利用计算机多核资源在同时执行,此时多个任务为并行关系。

    并发:计算机在同时处理多个问题的时候,内核在不同的任务之间不断的切换达到好像多个任务被同时执行的结果,实际上每个时刻只有一个任务占据内核

    CPU时间片:

    CPU时间片:如果一个进程占有CPU此时我们称该进程占有CPU时间片,多个进程任务会轮流占有CPU时间片形成并发效果。

    进程控制块(PCB):

    进程控制块:进程创建后会自动在内存开辟一块空间存放进程的基本信息。

    僵尸进程和孤儿进程:

    孤儿进程:父进程先于子进程退出,此时子进程就会成为孤儿进程。孤儿进程会被系统进程收养,此时系统进程就会成为该进程的新父进程。

    僵尸进程:子进程先于父进程退出,父进程没有处理子进程的退出状态,此时子进程就会成为僵尸进程。僵尸进程结束时会存留部分的PCB在内存中,大量的僵尸进程会浪费系统的资源。

    那么如何避免僵尸进程?

    1、阻塞父进程,等待子进程退出的时候父进程可以及时处理子进程的退出状态

    2、新建一个二级子进程,二级子进程的父进程及时退出,这时候二级子进程就会成为孤儿进程,孤儿进程会被系统进程收养,同时孤儿进程永远不会成为僵尸进程。

    2.进程属性

    p.name   # 进程名称

    p.pid      #进程PID(Process ID)

    p.daemon  #默认值为False 表示主进程退出不会影响子进程

          如果设置为True 则主进程退出子进程也会退出 

    p.is_alive()   # 查看进程是否在生命周期

    3.进程方法

    3.1、获取当前进程的PID

    os.getpid()

    3.2、获取父进程的PID

    os.getppid()

    4.进程的创建和关闭

    进程的关闭:

    '''
    进程退出
    功能 : 退出一个进程
    参数 : 表示自定义的进程退出状态  整数
    '''
    os._exit(status)
    
    '''
    功能 : 退出一个进程
    参数 : 默认为0
            如果传入一个整数则同 _exit()
        传入一个字符串。则在对出时打印该字符串
    '''
    sys.exit([status])

    1、使用os.fork()创建进程

    注意:

    1、子进程会复制父进程的全部代码和内存空间(父子的内存空间是相互独立的)

    2、子进程从fork的下一句开始执行

    3、if elif else 结构判断fork返回值的不同使得父子进程执行不同几乎是固定搭配

    4、父子进程各自独立运行,运行顺序不一定

    import os
    from time import sleep
    
    '''
    功能:创建进程
    参数:无
    返回值:失败返回一个负数
            成功:在原进程中返回新进程的PID,在新进程中返回0
    '''
    pid =os.fork()
    
    if pid<0:
        print("Create process error")
    elif pid ==0:
        sleep(1)
        print("Child PID",os.getpid())
        print("Get parent PID",os.getppid())
    else:
        print("Parent PID",os.getpid())
        print("Get child PID",pid)

    2、使用multiprocessing模块创建进程

    from multiprocessing import Process
    
    # 编写进程函数
    def fun():
        print("子进程事件")
    
    # 创建进程对象
    p = Process(target = fun)
    
    # 启动进程
    p.start()
    
    # 回收进程  父进程阻塞等待回收子进程 想当os.wait()
    p.join()

     

    5.进程之间的通信(常用的为消息队列和套接字)

    进程空间相对独立,所以说不同的进城之间需要专门的方法进行通信。常用的通信方法有如下几种:管道、消息队列、共享内存、信号量、套接字

    5.1、通信管道(Pipe)

    通信原理:在内存中开辟管道空间,生成管道操作对象,多个进程使用同一管道对象进行读写即可实现通信。

    from multiprocessing import Process,Pipe
    import os,time
    
    # 创建管道对象
    '''
    功能 : 创建管道
    参数 : 默认表示双向管道
            如果设置为False 则为单向管道
    
    返回值 : 表示管道两端的读写对象
              如果是双向管道则两端都可以读写
              如果是单向管道则fd1只读  fd2只写
    '''
    fd1,fd2 = Pipe()
    
    '''
    fd1.send
    功能:向管道写入内容
    参数:要写入的数据
    
    * 可以写入python的数据类型
    '''
    def fun(name):
        time.sleep(3)
        fd1.send(name)
    
    jobs = []
    for i in range(5):
        p = Process(target = fun,args=(i,))
        jobs.append(p)
        p.start()
    
    for i in range(5):
        '''
        功能 : 从管道读取内容
        返回值:读到的内容
        *当管道为空则阻塞
        '''
        data =fd2.recv()
        print(data)
    
    for i in jobs:
        i.join()

    5.2、消息队列

    原路:在内存中建立队列模型,进程通过队列对象将消息存入队列,或者从队列中取出消息,完成进程间的通信。

    from multiprocessing import Queue
    from time import sleep
    # 创建消息队列
    '''
    功能: 创建队列对象
    参数: 表示队列中最多存放多少个消息
    返回值 : 队列对象
    '''
    q =Queue(3)
    '''
    q.put(data,[block,timeout])
    功能 : 向队列存入消息
    参数 : data 要存入的内容 python数据
            block 默认队列满时会阻塞,设置为False则为非阻塞
            timeout  超时检测 
    '''
    q.put(1)
    sleep(1)
    print(q.empty())
    q.put(2)
    q.put(3)
    print(q.full())
    
    '''
    q.get([block,timeout])
    功能 : 从队列获取消息
    参数 : block 默认当队列为空时阻塞,设置为False则为非阻塞
            timeout 超时检测
    '''
    print(q.get())
    print(q.qsize())
    
    q.close()

    5.3、进程间通信之共享内存(Value,Array)

    通信原理:在内存空间开辟一个区域,对多个进程可见,进程可写入内容或者读取内容,但是每次写入的内容会覆盖之前的内容。

    from multiprocessing import Value,Array
    '''
    功能:开辟共享内存空间
    参数:
        ctype 字符串,表示共享内存中药存储的数据类型
              常用类型: int --> 'i'
                        float --> 'f'
                        char(bytes)  --> 'c'
        obj 共享内存中放入的初始化数据
    obj.value 对该属性的修改和使用即对共享内存数据的修改和使用
    '''
    obj = Value(ctype, obj)
    ''
    功能:创建共享内存
    参数:
        ctype 要存储的数据类型
        obj 存入一个结构化数据(列表 bytes字符串) 表示共享内存中的初始化数据
    
        传入正整数 表示在共享内存中开辟指定大小的数据空间 
    返回值:共享内存对象
            可以通过遍历获取每个值,支持索引操作
            如果存入的是字符串,可以通过obj.value直接打印整个字符串
    '''
    obj = Array(ctype,obj)

    5.4、信号量

    原理:给定一个数量,多个进程均可见。多个进程可以通过方法操作数量,达到协同工作的目的。

    '''
    功能:创建信号量对象
    参数:信号量的初始值
    返回值:信号量对象
    '''
    from multiprocessing import Semaphore
    sem = Semaphore(num)
    
    sem.acquire()  # 将信号量减1 当信号量为0会阻塞
    sem.release()  # 将信号量加1
    sem.get_value()  # 获取信号量数量

    6.使用进程池管理进程

    产生原因: 如果有大量任务需要多进程完成,则可能要频繁的创建删除进程,此时给计算机带来的压力较大。
    
    原理 : 创建一定量的进程作为进程池,用来处理事件。事件处理完毕后不销毁进程,而是继续等待处理其他的事件。直到所有待处理事件结束再统一销毁进程。增加进程的重复利用,降低资源消耗。
    
    
    使用方法 
    1. 创建进程池,方式适当的进程
    2. 将要做的事件放入进程池等待队列
    3. 不断取事件使用进程池中进程执行,直到所有事件处理完毕
    4. 关闭进程池,回收进程
    
    from multiprocessing import Pool 
    
    Pool(processes)
    功能 : 创建进程池对象
    参数 : 指定进程池中进程的数据量,默认根据系统自动判定
    
    pool.apply_async(func,args,kwds)
    功能:使用进程池中的进程执行相应函数
    参数: func  进程事件函数
           args  元组  给func按位置传参
           kwds  字典  给func按键值传参
    返回值 : 返回函数事件对象
    
    pool.apply(func,args,kwds)
    功能:使用进程池中的进程执行相应函数
    参数: func  进程事件函数
           args  元组  给func按位置传参
           kwds  字典  给func按键值传参
    
    
    pool.close()
    功能 : 关闭进程池,不能再添加新的事件
    
    pool.join()
    功能:阻塞等待回收进程池进程
    
      
    pool.map(func,iter)
    功能:将要做的事件加入进程池
    参数 : func  事件函数
            iter  迭代对象
    返回值: 函数的返回值列表

     

  • 相关阅读:
    服务器安装宝塔面板
    CentOS7操作SSH/SSHD服务(查看/启动/重启/自启)
    CentOS服务器升级Linux版本
    阿里云云服务器漏洞修复
    Linux服务器安装Docker
    服务器安装Nginx
    服务器端简单Demo
    实现博客内容折叠
    [转]珍惜时间,做好规划——致大学过半的你们
    【LeetCode】9. 回文数
  • 原文地址:https://www.cnblogs.com/leijing0607/p/7511630.html
Copyright © 2011-2022 走看看