在了解进程之后,我们可以做一个多线程的聊天室
服务端
import socket from multiprocessing import Process def talk(conn): conn.send(b‘connected‘) ret = conn.recv(1024) print(ret) if __name__ == ‘__main__‘: sk = socket.socket() sk.bind((‘127.0.0.1‘, 8080)) sk.listen() while True: conn,addr = sk.accept() p = Process(target=talk,args=(conn,)) p.start() conn.close() sk.close()
客户端
import socket sk = socket.socket() sk.connect((‘127.0.0.1‘,8080)) ret = sk.recv(1024) print(ret) msg = input(‘>>>‘) sk.send(msg.encode(‘utf-8‘)) sk.close()
我们不论建立几个客户端都可以做到和服务端互动,他们每一个都是自己独立的线程
守护进程 子进程会在主进程结束时结束
# start 开启一个进程 # join 用join可以让主进程等待子进程结束 # 守护进程 # 守护进程会随着主进程的代码执行结束而结束 # 正常的子进程没有执行完的时候主进程要一直等着 import time from multiprocessing import Process def func(): print(‘--‘*10) time.sleep(15) print(‘--‘*10) def cal_time(): while True: time.sleep(1) print(‘过去了1秒‘) if __name__ == ‘__main__‘: p = Process(target=cal_time) p.daemon = True # 一定在开启进程之前设置 p.start() p2 = Process(target=func) # 15s p2.start() for i in range(100): # 10s time.sleep(0.1) print(‘*‘*i) p2.join() # 守护进程的进程的作用: # 会随着主进程的代码执行结束而结束,不会等待其他子进程 # 守护进程 要在start之前设置 # 守护进程中 不能再开启子进程
进程的其他方法
import time from multiprocessing import Process # def func(): # print(‘wahaha‘) # time.sleep(5) # print(‘qqxing‘) # if __name__ == ‘__main__‘: # p = Process(target=func) # p.start() # print(p.is_alive()) # # time.sleep(0.1) # p.terminate() # 关闭进程 异步 # print(p.is_alive()) # ??? # time.sleep(1) # print(p.is_alive()) # p.is_alive() # 是否活着 True代表进程还在 False代表进程不在了 # p.terminate() # 结束一个进程,但是这个进程不会立刻被杀死 # 属性 # pid 查看这个进程 进程id # name 查看这个进程的名字 # def func(): # print(‘wahaha‘) # time.sleep(5) # print(‘qqxing‘) # if __name__ == ‘__main__‘: # p = Process(target=func) # p.start() # print(p.name,p.pid) # p.name = ‘哇哈哈哈‘ # print(p.name) # class MyProcess(Process): # def run(self): # print(‘wahaha‘,self.name,self.pid) # time.sleep(5) # print(‘qqxing‘,self.name,self.pid) # if __name__ == ‘__main__‘: # p = MyProcess() # p.start() # print(p.pid) # 进程中的其他方法 # 守护进程 p.daemon = True # 两个方法 p.is_alive() p.terminate() # 两个属性 p.pid p.name
锁 在一个主线程开启多个子线程时,这几个子线程的数据是隔离的,但是当他们都与主进程互动时,难免会产生数据混乱,这种情况我们叫做
数据不安全,解决办法就是在进程中加锁
# from multiprocessing import Lock # lock = Lock() # lock.acquire() # 需要锁 拿钥匙 # lock.acquire() # 需要锁 阻塞 # # lock.release() # 释放锁 还钥匙 # 锁 就是在并发编程中 保证数据安全 # 多进程 实现 并发 import json import time import random from multiprocessing import Lock from multiprocessing import Process def search(i): with open(‘ticket‘) as f: print(i,json.load(f)[‘count‘]) def get(i): with open(‘ticket‘) as f: ticket_num = json.load(f)[‘count‘] time.sleep(random.random()) if ticket_num > 0: with open(‘ticket‘,‘w‘) as f: json.dump({‘count‘:ticket_num-1},f) print(‘%s买到票了‘%i) else: print(‘%s没票了‘%i) def task(i,lock): search(i) # 查看票 lock.acquire() get(i) # 抢票 lock.release() if __name__ == ‘__main__‘: lock = Lock() for i in range(20): # 20个人同时抢票 p = Process(target=task,args=(i,lock)) p.start()
当我们需要同时几个进程的时候,就相当于多给几个钥匙,这种情况叫信号量
# 信号量 from multiprocessing import Semaphore # sem = Semaphore(4) # sem.acquire() # 需要钥匙 # print(0) # sem.acquire() # 需要钥匙 # print(1) # sem.acquire() # 需要钥匙 # print(2) # sem.acquire() # 需要钥匙 # print(3) # sem.release() # sem.acquire() # 需要钥匙 # print(4) import time import random from multiprocessing import Semaphore from multiprocessing import Process def sing(i,sem): sem.acquire() print(‘%s : 进入 ktv‘%i) time.sleep(random.randint(1,10)) print(‘%s : 出 ktv‘%i) sem.release() # 迷你唱吧 20个人,同一时间只能有4个人进去唱歌 if __name__ == ‘__main__‘: sem = Semaphore(4) for i in range(20): Process(target=sing,args=(i,sem)).start()
event模块
可以控制进程的阻塞
# 事件 # 所有的阻塞 都是同步 # recv accept input sleep # 阻塞多个进程 异步阻塞 # lock 10进程 # 事件 —— 异步阻塞 # 事件 标志 同时 是所有的进程 都陷入阻塞 from multiprocessing import Event #事件 # e = Event() # 实例化一个事件 标志/交通信号灯 # e.set() # 将标志变成非阻塞/交通灯变绿 # e.wait() # 刚实例化出来的一个事件对象,默认的信号是阻塞信号/默认是红灯 # # 执行到wait,要先看灯,绿灯行红灯停,如果在停的过程中灯绿了, # # 就变成非阻塞了 # e.clear() # 将标志又变成阻塞/交通灯变红 # # e.is_set() # 是否阻塞 True就是绿灯 False就是红灯 # 红绿灯 import time import random from multiprocessing import Process from multiprocessing import Event def traffic_light(e): while True: if e.is_set(): time.sleep(3) print(‘红灯亮‘) e.clear() # 绿变红 else: time.sleep(3) print(‘绿灯亮‘) e.set() # 红变绿 def car(i,e): e.wait() print(‘%s车通过‘%i) if __name__ == ‘__main__‘: e = Event() # 立一个红灯 tra = Process(target=traffic_light,args=(e,)) tra.start() # 启动一个进程来控制红绿灯 for i in range(100): if i%6 == 0 : time.sleep(random.randint(1,3)) car_pro = Process(target=car, args=(i,e)) car_pro.start()
当我们想要在几个子进程间调用数据时,使用队列方法
# 进程之间的通信 # lock # 1 lock.acquire # 2 lock.acquire # sem # e # ‘hello‘ --> 子进程 # 子进程1 ‘hello’ --> 子进程2 from multiprocessing import Queue # q = Queue(3) # q.put(1) # q.put(2) # q.put(3) # q.put(4) # # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get()) # 如果队列里已经没有值了 就会阻塞等待有一个值 #1.进程之间通信 可以使用multiprocessing 的 Queue模块 #2.队列有两种创建方式 第一种不传参数 这个队列就没有长度限制 ;传参数,创建一个有最大长度限制的队列 #3.提供两个重要方法;put get #4.qsize from multiprocessing import Process from multiprocessing import Queue # def q_put(q): # q.put(‘hello‘) # # def q_get(q): # print(q.get()) # # if __name__ ==‘__main__‘: # q = Queue() # p = Process(target=q_put,args=(q,)) # p.start() # p1 = Process(target=q_get, args=(q,)) # p1.start() # 通过队列实现了 主进程与子进程的通信 子进程与子进程之间的通信 # 生产者消费者模型 # 我要生产一个数据 然后 给一个函数 让这个函数依赖这个数据进行运算 拿到结果 —— 同步过程 # 做包子 和 吃包子 import time def producer(q): # 生产者 for i in range(100): q.put(‘包子%s‘%i) def consumer(q): # 消费者 for i in range(100): time.sleep(1) print(q.get()) if __name__ == ‘__main__‘: q = Queue(10) # 托盘 p = Process(target=producer,args=(q,)) p.start() c1 = Process(target=consumer, args=(q,)) c2 = Process(target=consumer, args=(q,)) c1.start() c2.start() # 首先 对于内存空间来说 每次只有很少的数据会在内存中 # 对于生产与消费之间的不平衡来说 # 增加消费者或者增加生产者来调节效率