• 多进程,锁


    一:多进程

    import os
    import time
    from multiprocessing import Process
    def func(args,args2):
        print(args,args2)#打印参数
        time.sleep(3)
        print('子进程 :', os.getpid())  #查看子进程进程号
        print('子进程的父进程 :', os.getppid())#查看子进程的父进程,多了一个p
        print(12345)
    
    if __name__ == '__main__':
        p = Process(target=func,args=('参数','参数2'))   # 注册
        # p是一个进程对象,还没有启动进程
        p.start()       # 开启了一个子进程
        print('*'*10)
        print('父进程 :',os.getpid()) # 查看当前进程的进程号
        print('父进程的父进程 :',os.getppid()) # 查看当前进程的父进程
    
    # 进程的生命周期
        # 主进程
        # 子进程
        # 开启了子进程的主进程 :
            # 主进程自己的代码如果长,等待自己的代码执行结束,
            # 子进程的执行时间长,主进程会在主进程代码执行完毕之后等待子进程执行完毕之后 主进程才结束

    打印结果: 先打印主进程,然后打印子进程。主进程结束执行子进程。

    **********
    父进程 : 3832
    父进程的父进程 : 2556
    参数 参数2
    子进程 : 5416
    子进程的父进程 : 3832
    12345

    二:多进程的中的几个方法(多进程即可指子进程,父进程这两个进程,也可指多个实例化两个进程)

    import time
    from multiprocessing import Process
    
    def func(arg1,arg2):
        print('*'*arg1)
        time.sleep(5)
        print('*'*arg2)
    
    if __name__ == '__main__':
        p = Process(target=func,args=(10,20))
        p.start()
        print('hahahaha')
        # p.join()     # 是感知一个子进程的结束,将异步的程序改为同步
        print('====== : 运行完了')

    这样就是正常打印,主进程执行完毕执行子进程

    hahahaha
    ====== : 运行完了
    **********
    ********************

    如果加上join之后,是感知一个子进程的结束,将异步的程序改为同步。也就是等待子进程结束后主进程关闭

    打印结果:

    hahahaha
    **********
    ********************
    ====== : 运行完了

    如果子进程是一个while循环的死循环,那么主进程就一直不会关闭。

    import os
    import time
    from multiprocessing import Process
    
    def func():
        while True:
            print('子进程开始')
            time.sleep(1)
            print('***我还在运行')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.daemon = True
    p.start()
        p.join()
        print('程序结束')

    打印结果:

    子进程开始
    ***我还在运行
    子进程开始
    ***我还在运行

    总是在子进程这里循环

    3小总结:

    process小知识:

    Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,
    表示一个子进程中的任务(尚未启动)
    
    强调:
    1. 需要使用关键字的方式来指定参数
    2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
    
    参数介绍:
    1 group参数未使用,值始终为None
    2 target表示调用对象,即子进程要执行的任务
    3 args表示调用对象的位置参数元组,args=(1,2,'egon',)
    4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
    5 name为子进程的名称

    进程常见关键字

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

    process模块里面属性:

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

    4开启多个子进程

    import os
    import time
    from multiprocessing import Process
    
    def func(filename,content):
        with open(filename,'w') as f:
            f.write(content*10*'*')
    
    if __name__ == '__main__':
        p_lst = []
        for i in range(10):
            p = Process(target=func,args=('info%s'%i,i))
            p_lst.append(p)
            p.start()
        for p in p_lst:p.join()   # 之前的所有进程必须在这里都执行完才能执行下面的代码
        print([i for i in os.walk(r'F:python10期day37day37')])
    
    # 同步 0.1 * 500  = 50
    # 异步 500 0.1    = 0.1
    # 多进程写文件
    # 首先往文件夹中写文件
    # 向用户展示写入文件之后文件夹中所有的文件名

    解析:他会在所有进程结束之后才能完成下面的print。

    5 开启多个子进程的第二种方式:

    import os
    from multiprocessing import Process
    
    class MyProcess(Process):
        def __init__(self,arg1,arg2):
            super().__init__()
            self.arg1 = arg1
    self.arg2 = arg2
    
    def run(self):
            print(self.pid)
            print(self.name)
            print(self.arg1)
            print(self.arg2)
    
    if __name__ == '__main__':
        p1 = MyProcess(1,2)
        p1.start()
        p2 = MyProcess(3,4)
        p2.start()
    
    # 自定义类 继承Process类
    # 必须实现一个run方法,run方法中是在子进程中执行的代码

    这种方式需要第一定义一个类,让他继承process,第二种是传参,需要初始化,然后是定义一个run方法,因为定义run方法之后才能执行start,然后在实例化二个对象。分别执行。

    打印结果:

    6356
    MyProcess-1
    1
    2
    3136
    MyProcess-2
    3
    4

    因为此进程是异步,所以process1和process2不确定谁最先打印,随机。super是执行process所有方法。

    6 多进程中的数据隔离原则

    # 进程 与 进程之间
    import os
    from multiprocessing import Process
    
    def func():
        global n   # 声明了一个全局变量
    n = 0       # 重新定义了一个n                
    print('pid : %s'%os.getpid(),n)
    
    if __name__ == '__main__':
        n = 100
        p = Process(target=func)
        p.start()
        p.join()
        print(os.getpid(),n)

    打印结果:

    pid : 6004 0
    1240 100

    注意:两个进程之间隔离,彼此不受影响。

    守护进程:                                                                                 

    # 子进程 -- > 守护进程
    import time
    from multiprocessing import Process
    
    def func():
        while True:
            time.sleep(0.2)
            print('我还活着')
    
    def func2():
        print('in func2 start')
        time.sleep(8)
        print('in func2 finished')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.daemon = True   # 设置子进程为守护进程
    p.start()
        p2 = Process(target=func2)
        p2.start()
        p2.terminate()     # 结束一个子进程
    time.sleep(1)
        print(p2.is_alive())  # 检验一个进程是否还活着
    print(p2.name)
        # i = 0
        # while i<5:
        #     print('我是socket server')
        #     time.sleep(1)
        #     i+=1
    
    # 守护进程 会 随着 主进程的代码执行完毕 而 结束
    # 在主进程内结束一个子进程 p.terminate()
        #  结束一个进程不是在执行方法之后立即生效,需要一个操作系统响应的过程
    # 检验一个进程是否活着的状态 p.is_alive()
    # p.name p.pid 这个进程的名字和进程号

    买火车票涉及的锁问题:

    # 锁
    
    # 火车票
    import json
    import time
    from multiprocessing import Process
    from multiprocessing import Lock
    
    # def show(i):
    #     with open('ticket') as f:
    #         dic = json.load(f)
    #     print('余票: %s'%dic['ticket'])
    
    def buy_ticket(i,lock):
        lock.acquire() #拿钥匙进门
    with open('ticket') as f:
            dic = json.load(f)
            time.sleep(0.1)
        if dic['ticket'] > 0 :
            dic['ticket'] -= 1
            print('33[32m%s买到票了33[0m'%i)
        else:
            print('33[31m%s没买到票33[0m'%i)
        time.sleep(0.1)
        with open('ticket','w') as f:
            json.dump(dic,f)
        lock.release()      # 还钥匙
    
    if __name__ == '__main__':
        # for i in range(10):
        #     p = Process(target=show,args=(i,))
        #     p.start()
    lock = Lock()
        for i in range(10):
            p = Process(target=buy_ticket, args=(i,lock))
            p.start()

    lock.release() 还钥匙         lock.acquire() 拿钥匙进门

    在此之前要引用锁这个模块,from multiprocessing import Lock

     

  • 相关阅读:
    CodeSmith入门教程
    AJAX调用实例
    药品监控增加表结构
    典型SQL 语句总结
    CRM中常用代码
    win2000sever+IIS5不能下载exe文件处理方法
    常用的文件对应的MIME类型
    数据库范式1NF 2NF 3NF BCNF
    多线程编程中如何更改UI值
    NHibernate学习笔记(2)—关系映射
  • 原文地址:https://www.cnblogs.com/12121wdw/p/8652811.html
Copyright © 2020-2023  润新知