• multiprocessing模块-process模块


    一、multiprocessing模块

    在python中大部分情况需要使用多进程,python提供了multiprocessing模块。

    multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

    与线程不同,进程没有任何共享状态,进程修改的数据 ,改动权在于该进程内。

    二、process模块

    process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。

    参数介绍:

    Process(group=None, target=None, name=None, args=(), kwargs={})
    ​
    1 group——参数未使用,值始终为None
    2 target——表示调用对象,即子进程要执行的任务
    3 args——表示调用对象的位置参数元组,args=(1,2,'egon',)
    4 kwargs——表示调用对象的字典,kwargs={'name':'egon','age':18}
    5 name——为子进程的名称

    方法介绍:

    1 obj.start():启动进程,并调用该子进程中的obj.run() 
    2 obj.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  
    3 obj.terminate():强制终止进程obj,不会进行任何清理操作,如果obj创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果obj还保存了一个锁那么也将不会被释放,进而导致死锁
    4 obj.is_alive():如果obj仍然运行,返回True
    5 obj.join([timeout]):主线程等待obj终止(强调:是主线程处于等的状态,而obj是处于运行的状态)。timeout是可选的超时时间,需要强调的是,obj.join只能join住start开启的进程,而不能join住run开启的进程 

    属性介绍:

    1 obj.daemon:默认值为False,如果设为True,代表obj为后台运行的守护进程,当obj的父进程终止时,obj也随之终止,并且设定为True后,obj不能创建自己的新进程,必须在obj.start()之前设置
    2 obj.name:进程的名称
    3 obj.pid:进程的pid
    4 obj.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
    5 obj.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

    1、在python中启动一个子进程

    from multiprocessing import Process
    import os
    ​
    def func():
        print('这是一个子进程——>进程号:', os.getpid(), '  主进程号:', os.getppid())
    ​
    ​
    if __name__ == '__main__':
        print('这是主进程——>进程号:', os.getpid(), '  主进程号(pycharm):', os.getppid())
        # 实例化一个子进程对象
        obj = Process(target=func)
        obj.start()     # 执行子进程对象
        print('执行了完了主进程的内容')
    ​
    # 输出
    这是主进程——>进程号: 3100   主进程号(pycharm): 6748
    执行了完了主进程的内容
    这是一个子进程——>进程号: 2392   主进程号: 3100

    2、给子进程传递参数

    from multiprocessing import Process
    import os
    ​
    ​
    def func(name, age):
        print('这是一个子进程——>进程号:', os.getpid(), '  主进程号:', os.getppid())
        print(f'这是一个子进程——>我的名字是{name},今年{age}')
    ​
    ​
    if __name__ == '__main__':
        print('这是主进程——>进程号:', os.getpid(), '  主进程号(pycharm):', os.getppid())
        # 实例化一个子进程对象
        obj = Process(target=func, args=('小杨', '18')) # args以元组的形式给子进程func函数传位置参数
                                   # kwargs以字典的形式给子进程func函数传关键字参数
                                   # kwargs={'name': '小杨', 'age': 18}
        obj.start()     # 执行子进程对象
        print('执行了完了主进程的内容')
        
    # 输出
    这是主进程——>进程号: 11936   主进程号(pycharm): 3676
    执行了完了主进程的内容
    这是一个子进程——>进程号: 2996   主进程号: 11936
    这是一个子进程——>我的名字是小杨,今年18

    3、同时开多个子进程

    from multiprocessing import Process
    import os
    ​
    ​
    def func(name, age):
        print(f'这是一个子进程——>进程号:{os.getpid()},主进程号:{os.getppid()},我的名字是{name},今年{age}')
    ​
    ​
    if __name__ == '__main__':
        print('这是主进程——>进程号:', os.getpid(), '  主进程号(pycharm):', os.getppid())
        count = [('小杨', 18), ('鲍勃', 20), ('艾伦', 55)]
        for lis in count:
            # 实例化一个子进程对象
            obj = Process(target=func, args=lis)   # args以元组的形式给子进程func函数传位置参数
            obj.start()     # 执行子进程对象
        print('执行了完了主进程的内容')
        
    # 输出
    这是主进程——>进程号: 12632   主进程号(pycharm): 9220
    执行了完了主进程的内容
    这是一个子进程——>进程号:10048,主进程号:12632,我的名字是小杨,今年18
    这是一个子进程——>进程号:16032,主进程号:12632,我的名字是鲍勃,今年20
    这是一个子进程——>进程号:12060,主进程号:12632,我的名字是艾伦,今年55

    4、join的用法

    obj.join([timeout]): 主进程等待子进程obj终止(强调:是主进程处于等的状态,而子进程obj是处于运行的状态)。timeout是可选的超时时间,需要强调的是,obj.join只能join住start开启的进程,而不能join住run开启的进程

    多个进程同时运行(注意,子进程的执行顺序不是根据启动顺序决定的)

    join——>属于同步阻塞:

    同步:在做A事件的时候发起B事件,必须等待B事件结束后才能继续做A事件

    阻塞:CPU不工作——>input accept recv recvfrom sleep connect......

    start——>属于异步非阻塞:

    异步:在做A事件的时候发起B事件,不用等待B事件结束就可以继续A事件

    非阻塞:CPU在工作(非输入输出阶段I/O)

    from multiprocessing import Process
    import random
    import time
    ​
    ​
    def mail(name, age):
        count = random.random()
        print(f'给{age}岁的{name}发了一封邮件!延迟{count}秒')
        time.sleep(count)      # 模拟网络延迟
        """
        多个进程同时运行(注意,子进程的执行顺序不是根据启动顺序决定的)
        """
    ​
    ​
    if __name__ == '__main__':
        info_list = [('小杨', 18), ('鲍勃', 20), ('艾伦', 55)]
        jo = []
        for info in info_list:
            obj = Process(target=mail, args=info)
            obj.start()
            jo.append(obj)
    ​
        # 将所有的子进程全部放入jo列表,在循环join所有子进程,就能等待所有子进程结束后在做操作
        for o in jo:
            o.join()
    ​
        # 所有的子进程结束的操作
        print('全部发送完毕')
        
    # 输出
    给20岁的鲍勃发了一封邮件!延迟0.19840279388911186秒
    给18岁的小杨发了一封邮件!延迟0.8891892863366903秒
    给55岁的艾伦发了一封邮件!延迟0.0434307277609951秒
    全部发送完毕

    5、多进程之间的数据是否隔离

    from multiprocessing import Process
    ​
    count = 1def func():
        global count
        count += 1if __name__ == '__main__':
        for i in range(10):
            obj = Process(target=func)
            obj.start()
        print(count)        # ————>1 主进程的count没有被改变说明进程之间的数据时隔离的
        
    # 输出
    1

    6、为什么在Windows中Process()必须放到if __name__ == '__main__':

    由于Windows没有fork,多处理模块启动一个新的Python进程并导入调用模块。

    如果在导入时调用Process(),那么这将启动无限继承的新进程(或直到机器耗尽资源)。

    这是隐藏对Process()内部调用的原,使用if __name__ == '__main__':,这个if语句中的语句将不会在导入时被调用。

    学习之旅
  • 相关阅读:
    AUDIT审计的一些使用
    HOW TO PERFORM BLOCK MEDIA RECOVERY (BMR) WHEN BACKUPS ARE NOT TAKEN BY RMAN. (Doc ID 342972.1)
    使用BBED理解和修改Oracle数据块
    Using Class of Secure Transport (COST) to Restrict Instance Registration in Oracle RAC [ID 1340831.1]
    调试利器GDB概念
    第4章 思科IOS
    第3章 ip地址和子网划分
    第2章 TCPIP
    2020年阅读过的黑客资源推荐篇
    第1章 计算机网络
  • 原文地址:https://www.cnblogs.com/XiaoYang-sir/p/14767576.html
Copyright © 2020-2023  润新知