### 9.4 Process模块 进程 ```python from multiprocess import Process p = Process(target=函数名,args=(参数1,)) 1.如何创建一个进程对象 对象和进程之间的关系: a.进程对象和进程并没有直接的关系 b.只是存储了一些和进程相关的内容 c.此时此刻,操作系统还没有接收到创建进程的指令 2.如何开启一个进程 通过p.start()开启一个进程,这个方法相当于给操作系统一个开启指令指令 start方法的异步非阻塞的特点: a.在执行这个方法的时候,我们既不等待进程开启,也不等待操作系统给我们的想要 b.这里只是负责同志操作系统去开启一个进程 开启一个子进程之后,主进程和子进程的代码完全异步 3.父进程和子进程之间的关系 a.父进程会等待子进程结束之后才结束 b.是为了挥手子进程的资源 4.不同操作系统中进程开启的方式 windows 通过(模块导入)再一次执行父进程文件中的代码来获取父进程中的数据 所以只要是不希望被子进程执行的代码,就写在if __name__ == '__main__'下 因为在进行导入的时候父进程文件中的__name__ != '__main__' linux/ios 正常的写就可以,没有if __name__ == '__main__'这件事情了 5.如何确认一个子进程执行完毕 join方法 开启了多个子进程,等待所有子进程结束 ``` #### 9.4.1 守护进程 ```python def son1(a,b): while True: print('is alive') time.sleep(0.5) def son2(): for i in range(5): print('in son2') time.sleep(1) if __name__ == "__main__": p = PROcess(target=son1,args=(1,2)) p.daemon = True p.start() p2 = Process(target=son2) p2.start() time.sleep(2) #守护进程是随着主进程的代码结束而结束 生产者消费者模型的时候 守护线程做对比的时候 #所有子进程都必须在主进程结束之前结束,由主进程挥手资源 ``` ```python # 有一个参数可以把一个子进程设置为一个守护进程 import time from multiprocessing import Process def son1(): while True: print('is alive') time.sleep(0.5) if __name__ == '__main__': p = Process(target=son1) p.start() # 异步 非阻塞 print(p.is_alive()) time.sleep(1) p.terminate() # 异步的 非阻塞 print(p.is_alive()) # 进程还活着 因为操作系统还没来得及关闭进程 time.sleep(0.01) print(p.is_alive()) # 操作系统已经响应了我们要关闭进程的需求,再去检测的时候,得到的结果是进程已经结束了 # 什么是异步非阻塞? # terminate ``` #### 9.4.2 面向对象方式的守护进程 #### 9.4.3 Process类的总结 ```python # Process类 # 开启进程的方式 # 面向函数 # def 函数名:要在子进程中执行的代码 # p = Process(target= 函数名,args=(参数1,)) #面向对象 #class 类名(Process): #def __init__(self,参数1,参数2): #self.a = 参数1 #self.b = 参数2 #super().__init__() #def run(self): #需要在紫禁城中执行的代码 #p = 类名(参数1,参数2) #p.start() 异步非阻塞 #p.terminate() 异步非阻塞 #p.join() 同步阻塞 #p.isalive() 获取当前进程状态 #daemon = True 设置为守护进程,守护进程会在主进程代码结束后结束 ``` #### ### 9.5 锁 #### 9.5.1 什么时候需要用锁 - 如果在一个并发条件下,涉及的某部分内容 - 是需要修改一些所有进程共享的数据资源 - 需要枷锁类维持数据的安全 - 在数据安全的基础上,才考虑效率问题 - 同步存在的意义 - 数据安全 #### 9.5.2 锁在代码中的应用顺序 - 在主进程中实例化lock = Lock() - 把这把锁传递给子进程 - 在子进程中 对需要枷锁的代码进行with lock: - with lock 相当于lock.acquire()和lock.release() - 在主进程需要加锁的场景: - 共享数据资源(文件、数据等) - 对资源进行修改删除操作 - 加锁之后能保证数据的安全性 但同时也降低了程序的执行效率 ```python import time import json from multiprocessing import Process,Lock def search_ticket(user): with open('ticket_count') as f: dic = json.load(f) print('%s查询结果 : %s张余票'%(user,dic['count'])) def buy_ticket(user,lock): # with lock: # lock.acquire() # 给这段代码加上一把锁 time.sleep(0.02) with open('ticket_count') as f: dic = json.load(f) if dic['count'] > 0: print('%s买到票了'%(user)) dic['count'] -= 1 else: print('%s没买到票' % (user)) time.sleep(0.02) with open('ticket_count','w') as f: json.dump(dic,f) # lock.release() # 给这段代码解锁 def task(user, lock): search_ticket(user) with lock: buy_ticket(user, lock) if __name__ == '__main__': lock = Lock() for i in range(10): p = Process(target=task,args=('user%s'%i,lock)) p.start() ``` #### 9.5.3 进程之间的通信(IPC) ```python # 通信 #进程之间的通信 - IPC(inter process communication) from multiprocessing import Queue,Process # 先进先出 def func(exp,q): ret = eval(exp) q.put({ret,2,3}) q.put(ret*2) q.put(ret*4) if __name__ == '__main__': q = Queue() Process(target=func,args=('1+2+3',q)).start() print(q.get()) print(q.get())# print(q.get()) # Queue基于 天生就是数据安全的 # 文件家族的socket pickle lock # pipe 管道(不安全的) = 文件家族的socket pickle # 队列 = 管道 + 锁 ```