什么是进程:正在运行的程序
主进程要等待子进程结束后才结束,因为主进程要等待子进程结束后帮他们收尸
创建进程的类:
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开启的进程
属性介绍:
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字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
开启子进程的方式一:
from multiprocessing import Process import time,os,random
def work(name): print('%s is running' %name) time.sleep(2) print('%s end' %name) if __name__ == '__main__': p=Process(target=work,args=('alex',)) p.start() print('主')
开启子进程的方式二:
class Work(Process): def __init__(self,name): super().__init__() # 重用父类的方法 self.name=name # 定义自己的名字 def run(self): print('%s is piaoing' %self.name) time.sleep(2) print('%s piao end' %self.name) if __name__ == '__main__': p=Work('wusir') p.start() print('主')
开启多个子进程:
# 开启多个子进程 def work(name): print('%s is running' %name) time.sleep(2) print('%s end' %name) if __name__ == '__main__': p1=Process(target=work,args=('alex',)) p2=Process(target=work,args=('alexx',)) p3=Process(target=work,args=('alexc',)) p1.start() p2.start() p3.start() print('主')
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 def work(): 2 print('子进程的pid:%s,父进程的pid:%s' %(os.getpid(),os.getppid())) 3 time.sleep(1000) 4 5 if __name__ == '__main__': 6 p1=Process(target=work) 7 p2=Process(target=work) 8 p3=Process(target=work) 9 p1.start() 10 p2.start() 11 p3.start() 12 print('主',os.getpid(),os.getppid()) 13 time.sleep(100000)
def work():
print('子进程的pid:%s,父进程的pid:%s' %(os.getpid(),os.getppid()))
time.sleep(1000)
if __name__ == '__main__':
p1=Process(target=work)
p2=Process(target=work)
p3=Process(target=work)
p1.start()
p2.start()
p3.start()
print('主',os.getpid(),os.getppid())
time.sleep(100000)
socket通信变成并发的形式:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8083)) while True: # 用户循环发送数据 msg=input('>>: ').strip() if not msg:continue # 因为服务端不会对一个空数据进行操作,所以要限制用户输入为空 phone.send(msg.encode('utf-8')) data=phone.recv(1024) # 接收服务端传来的数据 print(data.decode('utf-8')) phone.close()
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8083)) while True: # 用户循环发送数据 msg=input('>>: ').strip() if not msg:continue # 因为服务端不会对一个空数据进行操作,所以要限制用户输入为空 phone.send(msg.encode('utf-8')) data=phone.recv(1024) # 接收服务端传来的数据 print(data.decode('utf-8')) phone.close()
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import socket from multiprocessing import Process phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加 phone.bind(('127.0.0.1',8083)) # 绑定ip和端口 phone.listen(5) # 等待连接的个数,最大监听数 print('starting...') def talk(conn): while True: try: # 解决客户端异常断开 data=conn.recv(1024) print(data) if not data:break conn.send(data.upper()) except Exception: break conn.close() if __name__ == '__main__': # windows下start进程一定要写到这下面 while True: conn, addr = phone.accept() print('IP:%s,PORT:%s' % (addr[0], addr[1])) p=Process(target=talk,args=(conn,)) p.start() print('>>>>>::') phone.close()
import socket from multiprocessing import Process phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加 phone.bind(('127.0.0.1',8083)) # 绑定ip和端口 phone.listen(5) # 等待连接的个数,最大监听数 print('starting...') def talk(conn): while True: try: # 解决客户端异常断开 data=conn.recv(1024) print(data) if not data:break conn.send(data.upper()) except Exception: break conn.close() if __name__ == '__main__': # windows下start进程一定要写到这下面 while True: conn, addr = phone.accept() print('IP:%s,PORT:%s' % (addr[0], addr[1])) p=Process(target=talk,args=(conn,)) p.start() print('>>>>>::') phone.close()
每来一个客户端,都在服务端开启一个进程,如果并发来一个万个客户端,要开启一万个进程吗,你自己尝试着在你自己的机器上开启一万个,10万个进程试一试。
解决方法:进程池
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
s
from multiprocessing import Process import time def work(name,n): print('%s is piaoing' %name) time.sleep(n) print('%s piao end' %name) if __name__ == '__main__': start_time=time.time() p1=Process(target=work,args=('alex',1)) p2=Process(target=work,args=('wupeiqi',2)) p3=Process(target=work,args=('yuanhao',3)) # p1.start() # p2.start() # p3.start() # p3.join() #主进程等,等待子进程结束后,主进程再执行后面的代码 # p2.join() #主进程等,等待子进程结束后,主进程再执行后面的代码 # p1.join() #主进程等,等待子进程结束后,主进程再执行后面的代码 p_l=[p1,p2,p3] for p in p_l: p.start() for p in p_l: p.join() stop_time=time.time() print('主',(stop_time-start_time))
# 必须明确:p.join()是让谁等? # 很明显p.join()是让主线程等待p的结束,卡住的是主线程而绝非进程p,
# 主进程等待所有子进程执行完毕,必须在close或terminate之后
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
ss
from multiprocessing import Process import time def work(name,n): print('%s is piaoing' %name) time.sleep(n) print('%s piao end' %name) if __name__ == '__main__': p1=Process(target=work,args=('alex',1)) p1.start() p1.terminate() time.sleep(1) print(p1.is_alive()) # 关闭进程不会立即关闭,所以iis_alive立刻查看的结果有可能还存活 print('主') print(p1.name) print(p1.pid)