基于多进程实现并发的套接字通信和守护进程
一、关于进程之间内存的空间隔离
看以下的两个实例,比较一下区别:
实例一:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from multiprocessing import Process
'''
a = 66
def revise():
global a
a = 99
print('修改后的值:a=%d'%a)
if __name__ == '__main__':
revise()
print('全局的值a=%d'%a)'''
'''输出的结果:
修改后的值:a=99
全局的值a=99
实例二:
# 证明进程之间内存的空间隔离,各进程之间并不会相互影响
n = 100
def talk():
global n
n = 1
print('子进程修改设置:%d '%n)
if __name__ == '__main__':
p = Process(target=talk)
p.start() # 只是发送执行信号,并非立即执行
p.join() # 只有p进程运行结束,才会运行其他进程
print('main:%d'%n)
'''未加p.join()时:
main:100
子进程修改设置:1
# 添加p.join()后:
子进程修改设置:1
main:100
'''
由实例一和实例二可知:不同进程之间存在空间上的隔离,不会相互影响。
二、多进程通信
多进程通信以实例方式呈现,分为客户端和服务端。
客户端.py
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',3306))
while True:
msg = input('>>>:').strip()
if not msg:continue
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print('from server:',data.decode('utf-8'))
client.close()
服务端.py
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
# 多进程并发通信
from socket import *
from multiprocessing import Process
def talk(conn):
while True:
try:
data = conn.recv(1024)
if not data: break
print('from client:',data.decode('utf-8'))
conn.send(data.title())
except ConnectionResetError:
break
conn.close()
def server(ip,port):
server = socket(AF_INET, SOCK_STREAM)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind((ip,port ))
server.listen(5)
while True:
conn,addres = server.accept()
p = Process(target=talk,args=(conn,))
p.start()
server.close()
if __name__ == '__main__':
server('127.0.0.1',3306)
三、join方法的练习
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from multiprocessing import Process
import time
import random
def task(n):
time.sleep(random.randint(1,2))
print('-----%s------'%n)
if __name__ == '__main__':
p1 = Process(target=task,args=(1,))
p2 = Process(target=task,args=(2,))
p3 = Process(target=task,args=(3,))
p4 = Process(target=task,args=(4,))
问题1:保证优先运行进程4
p4.start()
p4.join()
p1.start()
p2.start()
p3.start()
#注意,放在if__name__=='__main__':下执行
'''此时,保证优先运行进程4,并输出
-----4------
-----3------
-----2------
-----1------
'''
问题2:保证按进程1、2、3、4顺序执行
p1.start()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join()
p4.start()
p4.join()
#同样放在if __name__ == '__main__':下运行
'''此时保证按顺序输出
-----1------
-----2------
-----3------
-----4------
'''
四、守护进程
1、理解:主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比崇祯皇帝身边的老太监,
崇祯皇帝已死老太监就跟着殉葬了。
2、注意:
1️⃣:守护进程会在主进程代码执行结束后就终止;
2️⃣:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children。
如果我们有两个任务需要并发执行,那么开一个主进程和一个子进程分别去执行就ok了,如果子进程的任务在主进程任务结束后就没有存在的必要了,
那么该子进程应该在开启前就被设置成守护进程。主进程代码运行结束,守护进程随即终止。
3、实例:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from multiprocessing import Process
import time
def task(name):
print('%s is running'%name)
time.sleep(2)
# p = Process(target=task,args=('进程2',))
# p.start() 会报错--> 'daemonic processes are not allowed to have children' 守护进程不允许再有子进程
if __name__ == '__main__':
p = Process(target=task,args=('进程1',))
p.daemon = True # --->> daemon表示守护进程,必须在进程启动前设置,在主进程结束后,也接着死亡
p.start()
p.join()
print('主进程')
'''
进程1 is running
主进程
'''
4、关于守护进程的练习,思考执行的结果是怎样的?
import time
from multiprocessing import Process
def fun1():
print(666)
time.sleep(1)
print('----fun1-----')
def fun2():
print(888)
time.sleep(2)
print('----fun2-----')
if __name__ == '__main__':
p1 = Process(target=fun1)
p2 = Process(target=fun2)
p1.daemon = True
p1.start()
p2.start()
print('----main----')
答案:
----main----
888
----fun2-----