1. 并发:多个进程同时在执行,如执行python文件时,启动多个进程, *** 作系统管理多个进程;
1> 同步: 可以理解成在多条车道(进程/线程)上,就只有一辆车在开,按代码的逻辑分支先在A车道跑,之后再走到B车道...
2> 异步: 可以理解成在多条车道上,有多辆车在开,各自路各自的
3> os.getpID():查看当前进程的进程号;
4> os.getppID()):查看当前进程的父进程号;
5> 以下代码进程的生命周期:
a> 主进程开启子进程后,主进程执行自己后面的代码;
b> 而子进程等到 *** 作系统调度后执行自己的代码;
c> 此时主进程和子进程都是在各自执行自己的代码 -- 异步;
e> 子进程执行时间长时,主进程会在主进程代码执行完毕后等待子进程执行完毕之后,主进程才会结束;
1 import os 2 import time 3 from multiprocessing import Process 4 def func(): 5 print('子进度启动...') 6 time.sleep(2) 7 print('子进程ID:',os.getpID()) #查看当前进程的进程号 8 print('子进程的父进程:', os.getppID()) 9 print('子进度结束...')10 11 if __name__ == '__main__':12 print('执行当前脚本的进程(父进程),开始:',os.getpID())13 p = Process(target=func) #注册14 p.start() #启动一个子进程,func方法在该子进程中执行15 print('执行当前脚本的进程(父进程),结束:',os.getpID())16 print('父进程的父进程ID:',os.getppID()) # 查看当前进程的父进程,即pycharm工具的进程ID17 # 从执行打印出来的信息可见, 主进程启动后,注册了一个子进度,没有等子进程启动执行func方法,就去执行自己的代码18 # 子进程从就绪状态到执行状态,执行代码后,结束子进程19 # 故主进程和子进程是异步的,不是同步的启动多个进程
6> 带参数启动多进程: p = Process(target=func,args=('参数1','参数2'))
1 import os 2 import time 3 from multiprocessing import Process 4 5 def func(*args): 6 print(args) 7 time.sleep(3) 8 print('子进程ID:', os.getpID()) 9 print('子进程的父进程ID:', os.getppID())10 print('子进程执行结束..')11 12 if __name__ == '__main__':13 14 p = Process(target=func,args=('星期一','星期二')) # 带参数函数注册进程15 p.start()16 print('主进程ID:',os.getpID())17 print('主进程的代码执行完')带参数启动多进程
2. 多进程常用的几个方法:
1> p.join():设置主进程阻塞,等待子进程执行完毕后再继续执行主进程的代码,即主进程等待子进程执行完毕后,再执行自己后面的代码;
1 import os 2 import time 3 from multiprocessing import Process 4 5 def func(*args): 6 print(args) 7 time.sleep(3) 8 print('子进程ID:', os.getpID()) 9 print('子进程执行结束..')10 11 if __name__ == '__main__':12 13 p = Process(target=func,args=('星期一','星期二')) # 带参数函数注册进程14 p.start()15 print('主进程ID:',os.getpID())16 p.join() # 主进程的代码执行到这里时,等待子进程执行并结束后,再执行主进程以下的代码,将程序在此处由异步 改为 同步17 print('等子进程执行完毕后,才会执行这里的代码。')18 print('主进程的代码执行完')p.join方法
3. 开启几十个进程后,各子进程异步执行,在主进程的某个代码处需要等待所有子进程执行完毕后,再继续执行后面的代码,实现如下
1 import os 2 import time 3 from multiprocessing import Process 4 5 def func(arg1,arg2): 6 print('子进程ID:', os.getpID()) 7 print("*" * arg1) 8 time.sleep(5) 9 print("*" * arg2)10 11 if __name__ == "__main__":12 p_List = []13 print('主进程ID:', os.getpID())14 for i in range(1,5):15 p = Process(target=func, args=(2*i, 8*i)) # 带参数函数注册进程16 p_List.append(p)17 p.start()18 # p.join() # 第一个子进程执行完毕后,再执行第二个子进程...直到最后一个子进程执行完毕后,再继续主进程后面的代码,即所有子进程和主进程都是同步的19 # p.join() # 此时的p指的是for循环最后一个进程,所以这样只能达到最后一个进程与主进程在这之后由异步变成同步,而其他的子进程与主进程仍是异步20 [p.join() for p in p_List] # 主进程要等待每一个异步执行的子进程执行完毕后,再继续执行后面代码,即每个异步子进程与主进程在这之后由异步变同步21 print('等子进程执行完毕后,才会执行这里的代码。')多进程由异步变同步
4. 应用场景:同时写500个文件,待文件全部写完之后,展示所有的文件名
1 import os 2 from multiprocessing import Process 3 4 def func(filename,content): 5 with open(filename,'w') as fs: 6 fs.write(content*'=') 7 8 if __name__ == "__main__": 9 p_List = []10 for i in range(1,5):11 p = Process(target=func,args=('info%s'%i, i)) # 多进程异步写4个文件,提升写文件的效率12 p_List.append(p)13 p.start()14 [i.join() for i in p_List] # 等待所有文件写完成后,才能展示所有文件名15 # 向用户展示写入文件之后,文件夹中所有的文件名16 print([j for j in os.walk(r'D:\old_boy\Day36\自己的')])多进程异步变同步的应用
5. 另一种开启多进程的方法(面向对象)
1> 自定义一个类,继承Process类;
2> 必须实现一个run()方法,即重写父类的run()方法,run方法的代码是在子进程中执行;
3> 自定义的类若想传参数,初始化方法__init__记得一定要调用一下父类的__init__(),因为父类的初始化方法中还有很多其他属性是需要用到的;
1 import os 2 from multiprocessing import Process 3 4 class MyProcess(Process): 5 def __init__(self,arg1,arg2): 6 super().__init__() # 若不调用父类的初始化方法,执行会报错 AttributeError 7 self.arg1 = arg1 8 self.arg2 = arg2 9 10 def run(self):11 print(self.pID) # 查看进程ID,和os.getpID()同功效12 print(self.name)13 print(os.getpID())14 print(self.arg1)15 16 def func(self):17 print(self.arg2)18 19 if __name__ == '__main__':20 print('主进程:',os.getppID())21 p1 = MyProcess(1,2)22 p1.start() # start方法触发了调用run方法,而因为子类重写了run方法,即这里就是调用了MyProcess的run()23 24 p2 = MyProcess(3,4)25 p2.start()开启多进程(面向对象)
6. 主进程和子进程的数据一般是完全隔离的,不共享的
1 import os 2 from multiprocessing import Process 3 4 def func(): 5 global n 6 n = 0 7 print('子进程ID:%s'%os.getpID(),n) 8 9 if __name__ == "__main__":10 n = 20011 p = Process(target=func)12 p.start()13 p.join()14 print('主进程ID: %s' %os.getpID(),n)15 # 从执行结果可以得出:主进程和子进程的数据一般是完全隔离的,不共享的;主子进程数据隔离
7. 使用多进程实现socket服务端的并发效果
1 import socket 2 from multiprocessing import Process 3 4 # 一个socket服务端开启多个进程与多个客户端通信 5 def server(conn): 6 ret = '你好。。'.encode('utf-8') 7 conn.send(ret) 8 msg = conn.recv(1024).decode('utf-8') 9 print(msg)10 conn.close()11 12 if __name__ == '__main__':13 sk = socket.socket()14 sk.bind(('127.0.0.1',8090))15 sk.Listen()16 while True:17 conn,addr = sk.accept()18 p = Process(target=server,args=(conn,))19 p.start()20 21 sk.close()server端
1 import socket 2 3 sk = socket.socket() 4 sk.connect(('127.0.0.1',8090)) 5 6 ret = sk.recv(1024).decode('utf-8') 7 print(ret) 8 msg = input('>>>>').encode('utf-8') 9 sk.send(msg)10 11 sk.close()clIEnt端
PS:1> 每一个程序重新运行时都是一个新的进程,那么只要我们把客户端运行设置为:重新打开一个平行的窗口运行而不是关闭当前窗口重新运行,就可实现多个客户端的效果
2>pycharm中的设置方法如下:pycharm工具栏---->run---->Edit Configurations---->Allow parallal run(在右上角的位置),勾上它即代表重新运行时是开一个新的窗口
3> 启动server端后,启动一个客户端,就会开启一个子进程与服务端通信,启动多个客户端(一般多个客户的代码是相同的)后,多个客户端与server端即建立了通信;
8. 守护进程:主进程的代码执行结束,子进程的代码也应该执行结束,子进程应该随着主进程的结束而结束,这即为守护进程
1> 一般默认情况下主进程是会等待子进程执行结束后,再结束主进程;
2> 而实际应用场景中,期望主进程的代码执行完成后,相关的子进程也结束;
3> 没有进行设置时,子进程不会结束;
1 import time 2 from multiprocessing import Process 3 4 def func(): # 向主进程报告自己的状态 5 while True: 6 time.sleep(0.5) 7 print('我还活着。') 8 9 if __name__ == "__main__":10 Process(target=func).start()11 i = 012 while i < 2: 13 print('我是一个sokect server')14 time.sleep(5)15 i += 116 17 # 从执行结果可见,主进程的逻辑代码执行完后,子进程一直在执行,主进程也一直在等待子进程执行结束18 # 而此时子进程不会自己结束子进程没有被守护
4> 设置子进程为守护进程:p.daemon = True,在p.start()前设置
1 import time 2 from multiprocessing import Process 3 4 def func(): # 向主进程报告自己的状态 5 while True: 6 time.sleep(0.5) 7 print('我还活着。') 8 9 if __name__ == "__main__":10 p = Process(target=func)11 p.daemon = True # 设置子进程为守护进程12 p.start()13 i = 014 while i < 2:15 print('我是一个sokect server')16 time.sleep(5)17 i += 1子进程被守护
5> 守护进程会随着主进程代码执行完毕而结束;
1 def func1(): # 向主进程报告自己的状态 2 while True: 3 time.sleep(0.5) 4 print('我还活着。') 5 6 def func2(): 7 print('in func3 start..') 8 time.sleep(9) 9 print('in func3 finished..')10 11 if __name__ == "__main__":12 p1 = Process(target=func1)13 p1.daemon = True # 设置子进程为守护进程14 p1.start()15 p2 = Process(target=func2)16 p2.start()17 i = 018 while i < 2:19 print('我是一个sokect server')20 time.sleep(2)21 i += 122 # 子进程1(守护进程)会随着主进程代码执行完毕而结束23 # 主进程代码执行完成后,子进程1执行结束,但是主进程仍在等待子进程2执行结束,因为子进程2没有被守护子进程的结束
6> 判断子进程是否活着:p.is_alive(),返回True表示活着,返回False表示死了;
7> p.terminate():结束进程,该方法执行后,进程不是立即就死了,而是有一个 *** 作系统响应的过程;
8> 获取进程名字:p.name
9> 获取进程ID:p.pID
1 def func1(): # 向主进程报告自己的状态 2 while True: 3 time.sleep(0.5) 4 print('我还活着。') 5 6 def func2(): 7 print('in func3 start..') 8 time.sleep(9) 9 print('in func3 finished..')10 11 if __name__ == "__main__":12 p1 = Process(target=func1)13 p1.daemon = True # 设置子进程为守护进程14 p1.start()15 p2 = Process(target=func2)16 p2.start()17 p2.terminate() # 结束一个子进程18 print(p2.is_alive()) # 结果为True,因为 *** 作系统回收p2进程没有那么快19 time.sleep(1)20 print(p2.is_alive()) # 判断子进程是否活着21 print(p2.name) # 当前进程的名字进程的方法
总结
以上是内存溢出为你收集整理的10_python进程全部内容,希望文章能够帮你解决10_python进程所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)