• 0510进程 multiprocess模块


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

    创建模块
    import os
    import time
    from multiprocessing import Process
    
    def func(n,name,num = 20):
        print(os.getpid(),os.getppid())
        time.sleep(1)
    
    if __name__ == '__main__':
        print(os.getpid(),os.getppid())  # process id,parent process id
        Process(target=func,args=[1,'alex',30]).start()    # func
        print('*'*20)
        time.sleep(0.5)
        print('*'*40)
        # p = Process(target=func)
        # p.start()
    
    # 主进程默认会等待子进程执行完毕之后才结束
    # 主进程和子进程之间的代码是异步的
    # 为什么主进程要等待子进程结束 回收一些子进程的资源
    # 开启一个进程是有时间开销的 :操作系统响应开启进程指令,给这个进程分配必要的资源
    强调: 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开启的进程。


    属性介绍:
    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字符的字符串。这个键的用途是为涉及网络连接的底层
           进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

    在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),在创建子进程的时候会自动 import 启动它的这个文件,
    而在 import 的时候又执行了整个文件。因此如果将process()直接写在文件中就会无限递归创建子进程报错。所以必须把创建子
    进程的部分使用if __name__ ==‘__main__’ 判断保护起来,import 的时候 ,就不会递归运行了。

    同步控制
    import os
    from multiprocessing import Process
    def func(exp):
    print(os.getpid(),os.getppid())
    result = eval(exp)
    with open('file','w') as f:
    f.write(str(result))

    if __name__ == '__main__':
    print(os.getpid(),os.getppid()) # process id,parent process id
    # 3*5+5/6
    p = Process(target=func,args=['3*5']) # func
    p.start()
    ret = 5/6
    p.join() # join方法能够检测到p进程是否已经执行完了,阻塞直到p执行结束
    with open('file') as f:
    result = f.read()
    ret = ret + int(result)
    print(ret
    )
    join :阻塞 直到 子进程结

    开启多个进程
    import os
    import time
    from multiprocessing import Process

    def process(n):
    print(os.getpid(),os.getppid())
    time.sleep(1)
    print(n)
    if __name__ == '__main__':
    p_lst = []
    for i in range(10):
    p = Process(target=process,args=[i,])
    p.start()
    p_lst.append(p)
    for p in p_lst:p.join() # 检测p是否结束 如果没有结束就阻塞直到结束 如果已经结束了就不阻塞
    print('求和')
    还有一种以继承Process类的形式开启进程的方式
    import os
    from multiprocessing import Process
    class Myprocess(Process):
    def __init__(self,*args):
    super().__init__()
    self.args = args
    def run(self):
    print(os.getpid(),self.name,self.pid)
    for name in self.args:
    print('%s和女主播聊天'%name)

    if __name__ == '__main__':
    print(os.getpid())
    p = Myprocess('yuan','wusir')
    p.start() # 在执行start的时候,会帮我们主动执行run方法中的内容
    进程中的数据隔离
    from multiprocessing import Process
    n = 100
    def func():
    global n
    n += 1
    print('son : ',n) #son : 101

    if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    p.join()
    print(n) #100
    守护进程
    import time
    from multiprocessing import Process

    def func():
    print('son start')
    while True:
    time.sleep(1)
    print('son')

    def func2():
    print('start :in func2')
    time.sleep(5)
    print('end : in func2')
    if __name__ == '__main__':
    p = Process(target=func)
    # 在一个进程开启之前可以设置它为一个守护进程
    p.daemon = True
    p.start()
    Process(target=func2).start()
    time.sleep(2)
    print('在主进程中')
    分析:
    主进程的代码 大概在2s多的时候就结束了
    p2子进程实在5s多的时候结束
    主进程结束
    p是在什么时候结束的?
    p是在主进程的代码执行完毕之后就结束了

    主进程会等待子进程的结束而结束
    守护进程的意义:
    子进程会随着主进程代码的执行结束而结束
    注意:守护进程不会关心主进程什么时候结束,我只关心主进程中的代码什么时候结束
    守护进程的作用:
    守护主进程,程序报活
    主进程开启的时候 建立一个守护进程
    守护进程只负责每隔1分钟 就给检测程序发一条消息
    进程中的其他属性和方法
    import time
    from multiprocessing import Process

    def func():
    print('wahaha')
    time.sleep(20)
    print('wahaha end')
    if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    print(p.is_alive())
    time.sleep(1)
    p.terminate() # 在主进程中结束一个子进程
    print(p.is_alive())
    time.sleep(0.5)
    print(p.is_alive())
    print(p.pid) #相当于self.pid 查看进程ID
    print(p.name) #相当于self.name 查看进程名

    使用多进程实现socket聊天并发-server

    server端
    import socket
    from multiprocessing import Process
    def func(conn):
        while True:
            msg = conn.recv(1024).decode('utf-8')
            print(msg)
            conn.send('sb'.encode('utf-8'))
        conn.close()
    
    if __name__ == "__main__":
        sk = socket.socket()
        sk.bind(('127.0.0.1', 9000))
        sk.listen()
        while True:
            conn, addr = sk.accept()
            Process(target=func,args=[conn,]).start()
        sk.close()
    
    client端
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1',9000))
    while True:
        inp = input('>>>').encode('utf-8')
        sk.send(inp)
        msg = sk.recv(1024).decode('utf-8')
        print(msg)
    sk.close()

    import os
    import time
    import random
    from multiprocessing import Process
    from multiprocessing import Lock
    def work(n,lock):
        lock.acquire()
        print('%s: %s in running'%(n,os.getpid()))
        time.sleep(random.random())
        print('%s:%s in done'%(n,os.getpid()))
        lock.release()
    
    if __name__ =='__main__':
    
        lock = Lock()
        for i in range(10):
            p = Process(target=work, args=(i,lock))
            p.start()

    抢票系统
    import json
    import time
    import random
    from multiprocessing import Process,Lock
    def chenck(i):
    with open('file')as f:
    count = json.load(f)
    print('percon%s,剩余%s张票'%(i,count['count']))
    time.sleep(random.random())

    def buy(i,lock):
    chenck(i)
    lock.acquire()
    with open('file')as f:
    count = json.load(f)
    time.sleep(random.random())#模拟读数据的网络延迟
    if count['count'] > 0:
    print('%s抢票成功'%i)
    else:
    print('%s抢票失败'%i)
    time.sleep(random.random())#模拟读数据的网络延迟

    with open('file','w')as f:
    count['count'] -= 1
    json.dump(count,f)
    lock.release()

    if __name__ == '__main__':
    lock = Lock()
    for i in range(10): #模拟并发10个客户端抢票
    Process(target=buy, args=[i, lock]).start()
    上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。
    加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速
    度却保证了数据安全。 虽然可以用文件共享数据实现进程间通信,但问题是: 1.效率低(共享数据基于文件,而文件是硬盘上的数据) 2.需要自己加锁处理

    信号量

    KTV 4个房子
    import time
    import random
    from multiprocessing import Process,Semaphore
    def ktv(i,sem):
        sem.acquire()
        print('person %s 进来唱歌了'%i)
        time.sleep(random.randint(1,5))
        print('person %s 从ktv出去了'%i)
        sem.release()
    
    if __name__ == '__main__':
        sem = Semaphore(4)
        for i in range(10):
            Process(target=ktv,args=(i,sem)).start()
    
    锁+计数器
    .acquire() 计数器-1
    计数器减为0 = 阻塞
    .release() 计数器+1

    事件--------------红绿灯

    multiprocess.Event(了解)

    状态 # 子进程 如何 受到状态的影响? # wait() 的方法 等待 ---> 信号 # 发送信号:通过事件来发送信号 # True set 把信号设置为True # False clear 把信号设置位False # 红绿灯 : # 车 进程 wait() 等红灯 # 根据状态变化 wait遇到True信号,就非阻塞 # 遇到False信号,就阻塞 # 交通灯 进程 红灯 --> False # 绿灯 --> True # 事件 # wait的方法 根据一个状态来决定自己是否要阻塞 # 状态相关的方法 # set 将状态改为T # clear 将状态改为F # is_set 判断当前的状态是否为T # from multiprocessing import Event # # 创建一个事件的对象 # e = Event() # print(e.is_set()) # 在事件的创世之初,状态为False # e.set() # e.wait() # print(e.is_set()) # e.clear() # print(e.is_set()) # e.wait() import time import random from multiprocessing import Process,Event def car(i,e): # 感知状态的变化 if not e.is_set(): # 当前这个事件的状态如果是False print('car%s正在等待'%i) # 这辆车正在等待通过路口 e.wait() # 阻塞 直到有一个e.set行为 # 等红灯 print('car%s通过路口'%i) def traffic_light(e): # 修改事件的状态 print('33[1;31m红灯亮33[0m') # 事件在创立之初的状态是False,相当于我程序中的红灯 time.sleep(2) # 红灯亮2s while True: if not e.is_set(): # False print('33[1;32m绿灯亮33[0m') e.set() elif e.is_set(): print('33[1;31m红灯亮33[0m') e.clear() time.sleep(2) if __name__ == '__main__': e = Event() Process(target=traffic_light,args=[e,]).start() for i in range(50): time.sleep(random.randrange(0,5,2)) Process(target=car,args=[i,e]).start()

    进程间通信——队列和管道(multiprocess.Queue、multiprocess.Pipe)

  • 相关阅读:
    PHP excel读取excel文件转换为数组
    PHP输出xls文件
    proxy_redirect参数的作用
    nginx反向代理批量实现https协议访问
    用lua nginx module搭建一个二维码
    canvas操作图片,进行面板画图,旋转等
    线性表
    什么是闭包
    简单注解扫描的思考
    编写自己的validate校验框架原理(转)
  • 原文地址:https://www.cnblogs.com/Mr-Murray/p/9026955.html
Copyright © 2020-2023  润新知