python学习笔记 day36 进程(二)
1. 开多个进程实现server与多个client同时通信
之前基于TCP的socket一个server端在同一时间只能跟一个client端通信,后来又讲了一个socketserver可以实现一个server端跟多个client端同时通信,现在使用进程,创建多个进程实现一个来完成server端与多个client端的通信过程:
# server.py import socket from multiprocessing import Process def talk(conn): while True: info=input(">>>") # info='connected' conn.send(bytes(info.encode("utf-8"))) ret=conn.recv(1024).decode("utf-8") 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,)) # 开多个子进程,来完成server端与client端的通信 p.start() # 来一个client连server 就会开一个进程来完成通信send recv conn.close() sk.close()
# client.py import socket sk=socket.socket() sk.connect(("127.0.0.1",8080)) while True: ret=sk.recv(1024) print(ret.decode("utf-8")) info=input(">>>") sk.send(bytes(info.encode("utf-8"))) sk.close()
# client2.py import socket sk=socket.socket() sk.connect(("127.0.0.1",8080)) while True: ret=sk.recv(1024) print(ret.decode("utf-8")) info=input(">>>") sk.send(bytes(info.encode("utf-8"))) sk.close()
运行结果:
2. 多进程的其他方法
strart()方法 是开启一个进程(交给操作系统去处理)
join(): 是主进程等待子进程执行完毕之后才会继续执行自己的(阻塞)
接下来讲一个守护进程: 子进程会随着主进程代码执行结束而结束;
正常子进程未执行玩的代码,主进程会一直等待子进程执行完毕,但是守护进程是子进程的代码会随着主进程代码执行结束而不再继续执行;
# 正常的子进程未执行完代码,主进程会一直等待子进程执行完毕 from multiprocessing import Process import time def cal_time(): while True: # 子进程执行该函数时会一直执行,然后主进程会一直等待子进程执行完毕 time.sleep(0.1) print("过去了一秒") if __name__=="__main__": p=Process(target=cal_time) # 开启一个新进程,执行cal_time()函数(死循环,正常子进程会一直执行,主进程会一直等待子进程执行) p.start() for i in range(10): time.sleep(0.1) print("*"*i) # 主进程执行1秒就结束了,但是由于子进程执行的cal_time是一个死循环,会一直等待子进程
运行结果:
但是如果创建的是一个守护进程(子进程未执行完的代码会随着主进程代码执行结束而结束):
其实下面的这个例子更能说明子进程是随着主进程代码执行结束而结束的~
首先需要明确一点,普通进程未执行完的代码,主进程代码即使执行完也会一直等着子进程执行完毕,但是一旦创建守护进程,守护进程未执行完的代码会随着主进程代码结束而结束(而不会等着普通进程执行完,虽然主进程会一直等着,但是由于主进程代码已经执行完了,所以守护进程代码也不再继续执行了,但是主进程会等着普通进程~)
from multiprocessing import Process import time def cal_time(): while True: # 由于创建的是守护进程,所以虽然子进程执行的是死循环,但是当主进程代码执行完毕之后,子进程代码就不再继续执行了 time.sleep(0.1) print("过去了一秒") def func(): print("+++++++++++++++++") time.sleep(3) # 普通进程2会睡三秒,主进程和守护进程只会执行一秒,所以在主进程和普通进程之间的这两秒 如果不再执行cal_time()输出过去了一秒,就证明守护进程其实是随着主进程代码结束而结束的 if __name__=="__main__": p1=Process(target=cal_time) # 开启一个新进程,执行cal_time()函数 p1.daemon=True # 表明创建的是一个守护进程,一定要在start()方法之前设置守护进程 p1.start() p2=Process(target=func) p2.start() # 启动普通进程2 for i in range(10): time.sleep(0.1) print("*"*i) # 主进程执行1秒就结束了,子进程也会立马结束~
运行结果(虽然看起来没什么差异,但是需要执行看一下,在主进程和普通进程差的那两秒,虽然主进程在等着普通进程,但是由于主进程代码已经执行完了,所以守护进程也不再继续执行了,表现为在那两秒没有输出)
总结一下,守护进程的作用:
1.守护进程未执行完的代码会随着主进程代码执行结束而结束;
2. 子进程设置为守护进程一定要在start()方法之前;
3. 当子进程设置为守护进程之后,在这个守护进程中就不能再继续创建子进程了(其实也没啥用)
3. 进程的其他方法:
1. p.is_alive()----查看进程是否还在
2. p.terminate()----杀死进程(一定要注意这里只是告诉操作系统,杀死进程的命令,但是真正执行是交给操作系统来完成的,所以发指令到被执行会有延迟)
from multiprocessing import Process import time def func(): print("hello") time.sleep(5) print("bye") if __name__=="__main__": p=Process(target=func) p.start() # 开启一个进程 print(p.is_alive()) # 查看进程是否在 time.sleep(0.1) # 是为了打印func函数中的语句,否则由于异步,主进程直接执行杀死指令,里面的代码可能没有被执行有可能没有被打印 p.terminate() # 告诉操作系统要杀死这个进程(但是操作系统什么时候执行不知道,所以会有延迟) print(p.is_alive()) # 这个时候打印进程是否还在,不一定进程被杀死,因为上面只是告诉操作系统杀死,但是操作系统未必立马执行 time.sleep(1) # 先睡一秒,操作系统就会执行完杀死进程的指令啦 print(p.is_alive())
运行结果:
4. 进程的两个属性:pid & name
from multiprocessing import Process def func(): print("hello,xuanxuan") if __name__=="__main__": p=Process(target=func) p.start() print(p.pid,p.name) # 打印进程的进程id 和进程名字
运行结果:
如果是想在进程内部打印进程id和进程名字,应该实现一个类:
from multiprocessing import Process class MyProcess(Process): # 自己创建的类必须继承Process类 def run(self): # 必须在类内实现run()方法,当调用p.start()方法时 会主动调用run()方法 print("hello,xuanxuan") print(self.pid,self.name) # 在子进程中打印进程id和进程名 if __name__=="__main__": p=MyProcess() p.start() print(p.pid,p.name) # 打印进程的进程id 和进程名字
运行结果: