并发编程之多进程篇之三

基于多进程实现并发的套接字通信和守护进程

  一、关于进程之间内存的空间隔离

    看以下的两个实例,比较一下区别:

    实例一: 

#!/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()
View Code

    服务端.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)
View Code

  

  三、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------
    '''
View Code

  问题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------   
    '''
View Code

  

  四、守护进程

    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-----
View Code

    

原文地址:https://www.cnblogs.com/schut/p/9011466.html