Python并发编程基础 №② 进程 进程间的数据隔离 守护进程 进程锁
1、进程的常规使用
1 import time 2 from multiprocessing import Process 3 4 5 def func(arg1): 6 print('func is running, arg1 is: ', arg1) 7 time.sleep(2) 8 print('func continue running!') 9 10 11 if __name__ == '__main__': # windows中运行 12 p = Process(target=func, args=('name',)) 13 p.start() 14 print('main process is running here!')
2、进程中的方法:join
1 import os, time 2 from multiprocessing import Process 3 4 5 def func(): 6 print('子进程%s在运行'%os.getpid()) 7 time.sleep(1) 8 print('子进程%s继续在运行' % os.getpid()) 9 10 11 if __name__ == '__main__': 12 print('主进程:', os.getpid(), '在运行!') 13 p = Process(target=func) 14 p.start() 15 16 # 是感知一个子进程的结束 17 p.join() # 将异步变同步,让主进程等待该子进程运行,直到结束。 18 19 print('====== : 运行完了')
3、生成多个进程的例子,并使用join
1 import os 2 from multiprocessing import Process 3 4 5 def write(filename, content): 6 print('it is writing', os.getpid()) 7 with open(filename, 'w') as f: 8 f.write(content * 10 * '*') 9 10 11 if __name__ == '__main__': 12 13 p_li = [] 14 for i in range(10): 15 p = Process(target=write, args=('file_no%d'%i, i)) 16 p_li.append(p) 17 p.start() 18 19 [p.join() for p in p_li] # 等待所有的进程运行完 20 print(os.listdir(os.getcwd())) # 查看当前目录下所有的子目录名称,是一个列表。 21 print([ i for i in os.walk(os.getcwd())]) # 列表推导式,列表中含元组 #[('D:\\python_bases\\day36', [], todo 是上面的列表 22 print('主进程:', os.getpid(), '马上结束运行。。。。')
4、使用继承来使用进程
1 from multiprocessing import Process 2 import os 3 4 5 class MyProcess(Process): 6 """ 7 定义自己的额进程类,继承Process 8 如果想实现初始化方法,必须带上Process的初始化方法 9 """ 10 def __init__(self, arg1, arg2): 11 super().__init__() # 必须加,否则报错 12 self.arg1 = arg1 13 self.arg2 = arg2 14 15 def run(self): 16 print("进程开启,id为:",os.getpid(),self.arg1, self.arg2) 17 18 19 if __name__ == '__main__': 20 print('主线程的id:', os.getpid()) 21 mp1 = MyProcess(1, 2) 22 mp1.start() # 如果run就和主进程id一样了! 23 24 mp2 = MyProcess(3, 4) 25 mp2.start()
5、进程间的数据隔离问题
1 import os 2 from multiprocessing import Process 3 4 n = 1000 5 6 7 def show_data_independ(num): 8 """ 9 演示进程间的数据隔离 10 :param num: n 11 :return: None 12 """ 13 global n # 声明了一个全局变量 14 #n = 10 # 重新定义了一个n 15 print('主进程传递过的n的值是:', num) 16 print('子进程中的n的值是:', n) 17 18 19 if __name__ == '__main__': 20 n = 100 21 p = Process(target=show_data_independ, args=(n,)) 22 p.start() 23 p.join() 24 print(os.getpid(), n)
6、守护进程的开启
1 import os, time 2 from multiprocessing import Process 3 4 5 def process_son_run(): 6 """ 7 非守护进程演示 8 主进程已经结束运行,但是其子进程还在继续运行,这我默认状态 9 :return: 10 """ 11 while 1: 12 time.sleep(0.2) 13 print('子进程%s正在运行。。。。。。'%os.getpid()) 14 15 def son_process_walk(): 16 print('son_process_walk started') 17 time.sleep(8) 18 print('son_process_walk finished') 19 20 21 if __name__ == '__main__': 22 23 p = Process(target=process_son_run) 24 25 # 必须在start前,如果开启,开启守护进程!(即主进程关闭则子进程一起关闭) 26 p.daemon = True 27 p.start() 28 29 p2 = Process(target=son_process_walk) 30 p2.start() 31 p2.terminate() # 结束一个子进程 32 print(p.name, p.pid) # 不是马上结束,需要一个过程! Process-1 13068 33 time.sleep(1) 34 print(p2.is_alive()) # 检验一个进程是否还活着 35 print('主进程结束运行了!') 36 37 # 守护进程 会 随着 主进程的代码执行完毕 而 结束 38 # 在主进程内结束一个子进程 p.terminate() 39 # 结束一个进程不是在执行方法之后立即生效,需要一个操作系统响应的过程 40 # 检验一个进程是否活着的状态 p.is_alive() 41 # p.name p.pid 这个进程的名字和进程号
7、进程锁的演示
1 import time,os,json 2 from multiprocessing import Process, Lock 3 4 ''' 5 模拟网络购票: 6 有网络延时的情况 7 ''' 8 9 10 def look_left(i): 11 """ 12 看还剩多少票 13 :return: 14 """ 15 with open('ticket') as f: 16 dic = json.load(f) 17 print('到杭州的火车票还剩%s张!'%dic['left']) 18 19 20 def buy(i, lock): 21 # lock.acquire() 22 time.sleep(i * 1) 23 # time.sleep(1) 如果等待时间太短,都会买到票,没法子,cpu6核的! 24 with open('ticket') as f: 25 dic = json.load(f) 26 27 if dic['left'] > 0: 28 print('\033[31m购买者%s买到票了\033[0m!' % i) 29 dic['left'] -= 1 30 else: 31 print('\033[32m购买者%s没买到票了\033[0m!' % i) 32 33 time.sleep(2) 34 with open('ticket', 'w') as f: 35 json.dump(dic, f) 36 # lock.release() 37 if __name__ == '__main__': 38 39 # for i in range(10): 40 # p = Process(target=look_left, args=(i,)) 41 # p.start() 42 lock = Lock() 43 44 for i in range(10): 45 Process(target=buy, args=(i, lock)).start() 46 47 48 # 没加锁前:1张票有三个人抢到 49 # todo 购买者0买到票了! 50 # todo 购买者1买到票了! 51 # todo 购买者2买到票了! 52 ''' 53 购买者3没买到票了! 54 购买者4没买到票了! 55 购买者5没买到票了! 56 购买者6没买到票了! 57 购买者7没买到票了! 58 购买者8没买到票了! 59 购买者9没买到票了! 60 '''
9、sock中server端并发提供服务
server端的代码:
1 import socket 2 from multiprocessing import Process 3 4 5 def serve(conn): 6 msg = conn.recv(1024).decode('utf-8') 7 print(msg) 8 conn.close() 9 10 11 if __name__ == '__main__': 12 13 sk = socket.socket() 14 sk.bind(('127.0.0.1', 8888)) 15 sk.listen() 16 # todo 如果在这sk.accept() 会将cpu资源耗尽!!! 17 try: 18 while True: 19 conn, addr = sk.accept() 20 conn.send('你好吗?'.encode('utf-8')) 21 Process(target=serve, args=(conn,)).start() 22 except: 23 sk.close()
client端的代码:
1 import socket 2 3 sk = socket.socket() 4 sk.connect(('127.0.0.1', 8888)) 5 6 msg = sk.recv(1024).decode('utf-8') 7 print(msg) 8 9 ipt = input('>>>').encode('utf-8') 10 sk.send(ipt) 11 12 sk.close()

浙公网安备 33010602011771号