• 040.Python进程和Join


    一  进程相关介绍

    1.1 进程的概念(process)

    • 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位
    • 资源分配:分配的是cpu和内存等物理资源
    • 进程号是程的唯标识
    • 同—个程序执行两次之后是两个进程
    • 进程和进程之间的关系:数据彼此隔离,通过 socket通信

    1.2 并行和并发

    并发:一个cpu同一时间不停执行多个程序

    并行:多个cpu同一时间不停执行多个程序

    1.3 进程的调度方法

    1. 先来先服努fcfs( first come first server):先来的先执行
    2. 短作业优先算法:分配的cpu多,先把短的算完
    3. 时间片轮转算法:每一个任务就枘行一个时间片的时间.然后驯执行其他的
    4. 多级反馈队列算法

    越是时间长的,cpu分配的资源越短,优先级靠后

    越是时间短的,cpu分配的资源越多

    1.4 进程三状态图

    (1)就绪(Read)状态:只剩下CPU需要执行外,其他所有資源都已分配完毕称为就绪状态。

    (2)执行(Running)状态:CPU开始执行该进程时称为执行状态。

    (3)阻塞(Blocked)状态:由于等待某个事件发生而无法行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成 input、申请缓中区不能满足等等。

    1.5 同步 异步 /阻塞 非阻塞

    场景在多任务当中

    同步:必须等我这件事干完了,你在干,只有一条主线,就是同步

    异步:没等我这件事情干完,你就在干了,有两条主线,就是异步

    阻塞:比如代码有了 input,就是阻塞,必须要输入一个字符串,否则代码不往下执行

    非阻塞:没有任何等待,正常代码往下执行

    • 同步阻塞:效率低,cpu利用不充分
    • 异步阻塞:比如 socketserver,可以同时连接多个,但是彼此都有recv
    • 同步非阻塞没有类似 input的代码,从上到下执行默认的正常情况代码
    • 异步非阻塞:效率是最高的,cpu过度充分,过度发热

    二 python进程的相关操作

    2.1 打印一个进程号

    import os
    from multiprocessing import Process
    #获取子进程的ID(当前进程)
    res = os.getpid()
    print ("子进程是:",res)
    #获取父进程id
    res = os.getppid()
    print ("父进程是:",res)

    执行

    [root@node10 python]# python3 test.py
    子进程是: 3452
    父进程是: 3294

    2.2 进程的基本语法

    import os
    from multiprocessing import Process
    #获取子进程的ID(当前进程)
    res = os.getpid()
    print ("子进程是:",res)
    #获取父进程id
    res = os.getppid()
    print ("父进程是:",res)
    def func():
            print("1子进程id>>>:%s,父进程id>>>:%s" % (os.getpid(),os.getppid()) )
    if __name__ == "__main__":
            print("2子进程id>>>:%s,父进程id>>>:%s" % (os.getpid(),os.getppid()) )
            # 创建子进程 target 是指定要完成的任务,后面接的是函数变量
            p = Process(target=func)
            # 调用子进程
            p.start()
    func()

    执行

    [root@node10 python]# python3 test.py
    子进程是: 3468
    父进程是: 3294
    2子进程id>>>:3468,父进程id>>>:3294
    1子进程id>>>:3468,父进程id>>>:3294
    1子进程id>>>:3469,父进程id>>>:3468

    2.3 带有参数的函数

    import os
    from multiprocessing import Process
    def func():
            for i in range(1,6):
                    print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    if __name__ == "__main__":
            print ("2子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
            p = Process(target=func)
            #调用子进程
            p.start()

    执行

    [root@node10 python]# python3 test.py
    2子进程id:3488,父进程id:3294
    1子进程id:3489,父进程id:3488
    1子进程id:3489,父进程id:3488
    1子进程id:3489,父进程id:3488
    1子进程id:3489,父进程id:3488
    1子进程id:3489,父进程id:3488

    2先于1执行

    import os
    from multiprocessing import Process
    def func():
            for i in range(1,6):
                    print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    if __name__ == "__main__":
            print ("2子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
            p = Process(target=func)
            #调用子进程
            p.start()
            n = 5
            for i in range(1,n+1):
                    print ("*"*i)

    执行

    [root@node10 python]# python3 test.py
    2子进程id:3494,父进程id:3294
    *
    **
    ***
    ****
    *****
    1子进程id:3495,父进程id:3494
    1子进程id:3495,父进程id:3494
    1子进程id:3495,父进程id:3494
    1子进程id:3495,父进程id:3494
    1子进程id:3495,父进程id:3494

    带参数

    import os
    import time
    from multiprocessing import Process
    def func(n):
            for i in range(1,n+1):
                    print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    if __name__ == "__main__":
            print ("2子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
            n = 5
            p = Process(target=func,args=(n,))
            #调用子进程
            p.start()
            for i in range(1,n+1):
                    print ("*"*i)

    执行

    [root@node10 python]# python3 test.py
    2子进程id:3508,父进程id:3294
    *
    **
    ***
    ****
    *****
    1子进程id:3509,父进程id:3508
    1子进程id:3509,父进程id:3508
    1子进程id:3509,父进程id:3508
    1子进程id:3509,父进程id:3508
    1子进程id:3509,父进程id:3508

    加延迟,即阻塞

    import os
    import time
    from multiprocessing import Process
    def func(n):
            for i in range(1,n+1):
                    time.sleep(0.1)
                    print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    if __name__ == "__main__":
            print ("2子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
            n = 5
            p = Process(target=func,args=(n,))
            #调用子进程
            p.start()
            for i in range(1,n+1):
                    time.sleep(0.1)
                    print ("*"*i)

    执行

    [root@node10 python]# python3 test.py
    2子进程id:3515,父进程id:3294
    *
    1子进程id:3516,父进程id:3515
    **
    1子进程id:3516,父进程id:3515
    ***
    1子进程id:3516,父进程id:3515
    ****
    1子进程id:3516,父进程id:3515
    *****
    1子进程id:3516,父进程id:3515

    修改阻塞时间

    import os
    import time
    from multiprocessing import Process
    def func(n):
            for i in range(1,n+1):
                    time.sleep(0.3)
                    print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    if __name__ == "__main__":
            print ("2子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))

          # 创建子进程,返回进程对象,如果有参数用args关键字参数进行指定
          # 对应的值是元组,参数赛到元组当中,按照传递次序排列

            n = 5
            p = Process(target=func,args=(n,))
            #调用子进程
            p.start()
            for i in range(1,n+1):
                    time.sleep(0.1)
                    print ("*"*i)

    执行

    2子进程id:3504,父进程id:3294
    *
    **
    ***
    1子进程id:3505,父进程id:3504
    ****
    *****
    1子进程id:3505,父进程id:3504
    1子进程id:3505,父进程id:3504
    1子进程id:3505,父进程id:3504
    1子进程id:3505,父进程id:3504

    2.4 进程之间数据彼此隔离

    import os
    import time
    from multiprocessing import Process
    count = 99
    def func():
            global count
            count += 1
            print ("子进程id:%s"%(os.getpid()))
            print (count)
    if __name__ == "__main__":
            p = Process(target=func)
            p.start()
            print ("主进程,count=",count)

    执行

    [root@node10 python]# python3 test.py
    主进程,count= 99
    子进程id:3527
    100

    主进程和子进程之间是隔离的,相当于是直接复制一份,不是直接延续主进程

    import os
    import time
    from multiprocessing import Process
    count = 99
    def func():
            global count
            count += 1
            print ("子进程id:%s"%(os.getpid()))
            print (count)
    if __name__ == "__main__":
            p = Process(target=func)
            p.start()
            time.sleep(1)
            print ("主进程,count=",count)

    执行

    [root@node10 python]# python3 test.py
    子进程id:3533
    100
    主进程,count= 99

    2.5 多进程之间的并发

    在程序并发时,因为cpu的调度策略问题,不一定谁先执行,谁后执行,任务的执行,是资源抢占的过程

    import os
    import time
    from multiprocessing import Process
    def func():
            print ("1子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    
    if __name__ == "__main__":
            for i in range(10):
                    Process(target=func).start()

    执行

    [root@node10 python]# python3 test.py
    1子进程id:3538,父进程id:3537
    1子进程id:3539,父进程id:3537
    1子进程id:3540,父进程id:3537
    1子进程id:3541,父进程id:3537
    1子进程id:3542,父进程id:3537
    1子进程id:3543,父进程id:3537
    1子进程id:3544,父进程id:3537
    1子进程id:3545,父进程id:3537
    1子进程id:3546,父进程id:3537
    1子进程id:3547,父进程id:3537

    把i作为参数

    import os
    import time
    from multiprocessing import Process
    def func(i):
            print("i=%s,1子进程id>>>:%s,父进程id>>>:%s" % (i,os.getpid(),os.getppid()) )
    
    
    if __name__ == "__main__":
            for i in range(10):
                    Process(target=func,args=(i,)).start()

    执行

    [root@node10 python]# python3 test.py
    i=0,1子进程id>>>:3577,父进程id>>>:3576
    i=1,1子进程id>>>:3578,父进程id>>>:3576
    i=2,1子进程id>>>:3579,父进程id>>>:3576
    i=3,1子进程id>>>:3580,父进程id>>>:3576
    i=4,1子进程id>>>:3581,父进程id>>>:3576
    i=5,1子进程id>>>:3582,父进程id>>>:3576
    i=6,1子进程id>>>:3583,父进程id>>>:3576
    i=7,1子进程id>>>:3584,父进程id>>>:3576
    i=8,1子进程id>>>:3585,父进程id>>>:3576
    i=9,1子进程id>>>:3 586,父进程id>>>:3576

    2.6 子进程和父进程之间的关系

    • 通常情况下,父进程(主进程)速度执行稍块,但是不绝对,在父进程执行所有代码完毕之后,会默认等待所有子进程执行完毕,然后在彻底程序,为了方便进程的管理
    • 如果不等待,子进程会变成僵尸程序,在后台不停的占用内存和cpu,因为进程太多,一时找不到,并不容易.
    import os
    import time
    from multiprocessing import Process
    def func(args):
            print("i=%s,1子进程id>>>:%s,父进程id>>>:%s" % (i,os.getpid(),os.getppid()) )
            print("end,args= ",args)
    
    if __name__ == "__main__":
            for i in range(10):
                    Process(target=func,args=(i,)).start()
            print("主进程执行结束")

    执行

    [root@node10 python]# python3 test.py
    i=0,1子进程id>>>:3591,父进程id>>>:3590
    end,args=  0
    i=1,1子进程id>>>:3592,父进程id>>>:3590
    end,args=  1
    i=2,1子进程id>>>:3593,父进程id>>>:3590
    end,args=  2
    i=3,1子进程id>>>:3594,父进程id>>>:3590
    end,args=  3
    i=4,1子进程id>>>:3595,父进程id>>>:3590
    end,args=  4
    i=5,1子进程id>>>:3596,父进程id>>>:3590
    end,args=  5
    i=6,1子进程id>>>:3597,父进程id>>>:3590
    end,args=  6
    i=7,1子进程id>>>:3598,父进程id>>>:3590
    end,args=  7
    主进程执行结束
    i=8,1子进程id>>>:3599,父进程id>>>:3590
    end,args=  8
    i=9,1子进程id>

    添加延迟阻塞

    import os
    import time
    from multiprocessing import Process
    def func(args):
            print("i=%s,1子进程id>>>:%s,父进程id>>>:%s" % (i,os.getpid(),os.getppid()) )
            time.sleep(0.3)
            print("end,args= ",args)
    
    if __name__ == "__main__":
            for i in range(10):
                    Process(target=func,args=(i,)).start()
            print("主进程执行结束")

    执行

    [root@node10 python]# python3 test.py
    i=0,1子进程id>>>:3616,父进程id>>>:3615
    i=1,1子进程id>>>:3617,父进程id>>>:3615
    i=2,1子进程id>>>:3618,父进程id>>>:3615
    i=3,1子进程id>>>:3619,父进程id>>>:3615
    i=4,1子进程id>>>:3620,父进程id>>>:3615
    i=5,1子进程id>>>:3621,父进程id>>>:3615
    i=6,1子进程id>>>:3622,父进程id>>>:3615
    i=7,1子进程id>>>:3623,父进程id>>>:3615
    主进程执行结束
    i=8,1子进程id>>>:3624,父进程id>>>:3615
    i=9,1子进程id>>>:3625,父进程id>>>:3615
    end,args=  6
    end,args=  0
    end,args=  3
    end,args=  4
    end,args=  7
    end,args=  1
    end,args=  2
    end,args=  5
    end,args=  8
    end,args=  9

    三  join的基本使用

    3.1 基本应用

    等待有子进程执行完毕之后,主进程在向下执行;

    import os
    import time
    from multiprocessing import Process
    def func():
            print("this is first thing")
    
    if __name__ == "__main__":
            p = Process(target=func)
            p.start()
            print("This is second thing")

    执行

    [root@node10 python]# python3 test.py
    This is second thing
    this is first thing

    first要先执行,使用阻塞延迟

    import os
    import time
    from multiprocessing import Process
    def func():
            print("this is first thing")
    
    if __name__ == "__main__":
            p = Process(target=func)
            p.start()
            time.sleep(0.2)
            print("This is second thing")

    执行

    [root@node10 python]# python3 test.py
    this is first thing
    This is second thing

    使用join

    import os
    import time
    from multiprocessing import Process
    def func():
            print("this is first thing")
    
    if __name__ == "__main__":
            p = Process(target=func)
            p.start()
            p.join()    #自动加锁
            print("This is second thing")

    执行

    [root@node10 python]# python3 test.py
    this is first thing
    This is second thing

    3.2 __name__相关认知

    打印__name__和__name__类型

    print (__name__)
    print (type(__name__))

    执行

    [root@node10 python]# python3 ceshi.py
    __main__
    <class 'str'>

    3.3 调用自定义的模块

    [root@node10 python]# vim mymoudle.py

    print ("123 defined by myself")
    a = 111222333

    调用

    import mymoudle
    print (mymoudle.a)

    执行

    [root@node10 python]# python3 ceshi.py
    123 defined by myself
    111222333

    或者

    from  mymoudle import a
    print (a)

    执行

    123 defined by myself
    111222333

    __name__:如果作为一个主文件执行,得到的时__main__,如果作为一个分模块导入,那么返回的时模块名称;是主进程,返回__main__ 不是主进程,返回模块名;

    [root@node10 python]# vi mymoudle.py

    print (__name__)

    执行

    [root@node10 python]# python3 mymoudle.py
    __main__

    当被调用时

    import  mymoudle

    再次执行

    [root@node10 python]# python3 ceshi.py
    mymoudle

    由于教程使用的是windows,它所执行的是引用的模式,所以必须使用(if __name__ == "__main__)判断主进程,我这里使用的时centos系统,底层的实现方式是forks实现的,可以不添加,直接可以使用,来源:老男孩教育https://www.oldboyedu.com/

    import os
    import time
    from multiprocessing import Process
    def func():
            print("this is first thing")
    
    #if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    p.join()
    print("This is second thing")

    执行

    [root@node10 python]# python3 test.py
    this is first thing
    This is second thing

    这样也不会报错,后面将直接使用linux的使用方式,如果有朋友使用windows系统做实验,请加上这个判断

    3.4 多个子进程通过join加阻塞,可以和主进程进行同步控制

    等子进程全部执行完毕之后,主进程在走

    import os
    import time
    from multiprocessing import Process
    def func(index):
            print("第%s封邮件已经发送..."%(index))
    
    for i in range(10):
            p = Process(target = func,args = (i,))
            p.start()
    print ("发出第十封邮件...")

    执行

    [root@node10 python]# python3 test.py
    第0封邮件已经发送...
    第1封邮件已经发送...
    第2封邮件已经发送...
    第3封邮件已经发送...
    第4封邮件已经发送...
    第5封邮件已经发送...
    第6封邮件已经发送...
    第7封邮件已经发送...
    发出第十封邮件...
    第8封邮件已经发送...
    第9封邮件已经发送...

    使用列表,让每一个进程使用join

    import os
    import time
    from multiprocessing import Process
    def func(index):
            print("第%s封邮件已经发送..."%(index))
    
    lst = []
    for i in range(10):
            p = Process(target = func,args = (i,))
            p.start()
            lst.append(p)
    for i in lst:
            i.join()
    print ("发出第十封邮件...")

    执行

    第0封邮件已经发送...
    第1封邮件已经发送...
    第2封邮件已经发送...
    第3封邮件已经发送...
    第4封邮件已经发送...
    第5封邮件已经发送...
    第6封邮件已经发送...
    第7封邮件已经发送...
    第8封邮件已经发送...
    第9封邮件已经发送...
    发出第十封邮件...

    使用第二种方法创建进程

    3.5 用自定义类的方式创建进程

    必须继承父类Process,里面必须用run命名方法;

    基本使用

    import os
    import time
    from multiprocessing import Process
    class MyProcess(Process):
            def run(self):
                    pass
    p = MyProcess()
    p.start()
    print ("主进程:{}".format(os.getpid()))

    执行

    [root@node10 python]# python3 test.py
    主进程:3823

    定义子进程

    import os
    import time
    from multiprocessing import Process
    class MyProcess(Process):
            def run(self):
                    print("1子进程id>>>:%s,父进程id>>>:%s" % (os.getpid(),os.getppid()) )
    p = MyProcess()
    p.start()
    print ("主进程:{}".format(os.getpid()))

    执行

    [root@node10 python]# python3 test.py
    主进程:3823
    1子进程id>>>:3824,父进程id>>>:3823

    3.6 带参数的子进程函数

    import os
    import time
    from multiprocessing import Process
    class MyProcess(Process):
            #这里需要传参,需要自己初始化,但是有需要调用父类方法
            def __init__(self,arg):
                    #调用一下父类的构造方法来进行初始化
                    super().__init__()
                    #传入参数
                    self.arg = arg
    
            def run(self):
                    print("1子进程id>>>:%s,父进程id>>>:%s" % (os.getpid(),os.getppid()) )
                    print (self.arg)
    lst = []
    for i in range(10):
            p = MyProcess("参数:%s"%(i))
            p.start()
            lst.append(p)
    for i in lst:
            i.join()
    print ("最后执行子进程:{}".format(os.getpid()))

    执行

    [root@node10 python]# python3 test.py
    1子进程id>>>:3845,父进程id>>>:3844
    参数:0
    1子进程id>>>:3846,父进程id>>>:3844
    参数:1
    1子进程id>>>:3847,父进程id>>>:3844
    参数:2
    1子进程id>>>:3848,父进程id>>>:3844
    参数:3
    1子进程id>>>:3849,父进程id>>>:3844
    参数:4
    1子进程id>>>:3850,父进程id>>>:3844
    参数:5
    1子进程id>>>:3851,父进程id>>>:3844
    参数:6
    1子进程id>>>:3852,父进程id>>>:3844
    参数:7
    1子进程id>>>:3853,父进程id>>>:3844
    参数:8
    1子进程id>>>:3854,父进程id>>>:3844
    参数:9
    最后执行子进程:3844
  • 相关阅读:
    【转】:java遍历List时动态添加和删除元素
    【转】:浅析 Comparable和 Comparator的区别
    【转】:Synchronized同步静态方法和非静态方法总结
    【转】:学习路线(自用)
    js原型链的理解
    关于浏览器切换标签或者移动端切换应用时,js不执行的解决方案
    .net core连接mongoDB
    首先从项目结构开始讲起
    iOS应用内支付(IAP)服务端端校验详解
    .net支付宝SDK接入这些坑你必须知道
  • 原文地址:https://www.cnblogs.com/zyxnhr/p/12353160.html
Copyright © 2020-2023  润新知