一、开启进程的两种方式
进程的定义:正在进行的一个过程或者说一个任务,是个抽象化的概念。
在开启子进程开辟新空间时,子进程需要拷贝父进程中的数据。
在 win 系统下,子进程会将父进程这个文件当成模块重新导入,需将发起开启子进程的操作放至main方法下;
在linux系统下,则不需要将开启子进程放至 main 方法下,但是为了系统的兼容性,一般都是统一放至 main 方法下。
方式一:
from multiprocessing import Process import time def task(name): print('%s is running...' % name) time.sleep(3) print('%s is done ...' % name) if __name__ == '__main__': p = Process(target=task, args=('we',)) # target 是表示需要执行的函数 # agrs() 括号里边传的参数(元组形式)是传入至 task 里边 p.start() # 仅仅是向操作系统发起了一个开启子进程的指令,并不是表示子进程已经开启完毕 print('main Process')
方式二:
1 from multiprocessing import Process 2 import time 3 class MyProcess(Process): # 自定义的一个进程(必须继承Process) 4 def run(self): # 这个是Process父类里边的一个绑定方法 5 print("%s is running..."%self.name) 6 time.sleep(3) 7 print("%s is done"%self.name) 8 9 10 if __name__ == '__main__': 11 p=MyProcess() # 实例化时需要用自己定义的类 12 p.start() # 向操作系统发起一个开启子进程的信号,但是并不表示子进程开启完 13 # 毕(实际上是调用该子进程的p.run()) 14 print('main Process')
二、进程(父进程和子进程)内存空间彼此隔离的验证
1.进程间数据不共享
1 from multiprocessing import Process 2 import time 3 x=100 4 def task(): 5 global x # 声明 x 为全局变量 6 x=0 7 print('I am done') 8 if __name__ == '__main__': 9 p=Process() 10 p.start() 11 time.sleep(3) # 若是没有这一步,则<可能>子进程还未执行完成直接调至执行父 12 # 进程的代码, 就是说,这一步是为了保证子进程能够顺利执行完成 13 print(x)
2.实现进程之间数据共享的方式
1 from multiprocessing import Process,Manager 2 import os 3 def Foo(dic,list): 4 dic[os.getpid()]=os.getpid() 5 list.append(os.getpid()) 6 print(list) 7 8 if __name__ == '__main__': 9 with Manager() as manager: 10 dic=manager.dict() # 造一个空字典,可以在多个进程键共享和传递 11 list=manager.list() # 造一个空列表,可在多个进程间共享和传递 12 # 实际上是每次都将列表复制一份,然后往里边加值 13 p_list=[] 14 for i in range(10): 15 p=Process(target=Foo,args=(dic,list)) 16 p.start() 17 p_list.append(p) 18 for p in p_list: 19 p.join() 20 print(dic)
结果如下图
三、进程对象方法或者属性
1.join (代表子进程的代码执行完毕)
1 from multiprocessing import Process 2 import time 3 def task(name): 4 print('%s is walking...'%name) 5 time.sleep(3) 6 print("%s is done..."%name) 7 8 if __name__ == '__main__': 9 p=Process(target=task,args=('BlackMan',)) 10 p.start() 11 p.join() # 代表子进程的代码已经执行完了 12 print('main Process')
2.多个子进程的运行
from multiprocessing import Process import time def task(x,y): print('%s is running...'%x) time.sleep(y) print('%s is done...'%x) if __name__ == '__main__': p_list=[] start=time.time() for i in range(1,4): p=Process(target=task,args=('Processing-%s'%i,i)) p_list.append(p) # 这一步不要忘记写,否则直接执行父进程代码之后才开 # 始执行子进程代码 p.start() # p.start()写在这里的运行过程是多个子进程可以同时运行,可以 #提高运行的效率 for p in p_list: # p.start() # p.start()如果写在这里运行过程就是先执行完一个子进程之 # 后,再执行另一个子进程(就是串行的定义),这种执行方式效率比较低 p.join() stop=time.time() print('creating Processing cost %s second'%(stop-start)) print("it's turn to main Processing")
2.pid (2.1 os.getpid()--获取当前进程的 id ;os.getppid()--获取父进程的id)
2.1需要用到 os 模块
# getpid() 获取当前进程的id号 # getppid() 获取父进程的id号 from multiprocessing import Process import time,os def task(x): print("My id is %s..."%os.getpid()) time.sleep(x) print('%s is gone...'%os.getpid()) if __name__ == '__main__': p=Process(target=task,args=(3,)) p.start() print(p.pid) # 从父进程角度查看子进程的 id 号 p.join() print('main Processing,%s'%os.getppid())
四、进程池
1 from multiprocessing import Pool 2 import time,os 3 4 def Foo(i): 5 time.sleep(2) 6 print('in the pool',os.getpid()) 7 return i+100 8 9 def Bar(arg): 10 print('exec done'.center(16,'-'),arg,os.getpid()) 11 12 if __name__ == '__main__': 13 pool=Pool(processes=2) # 允许进程池同时有4个进程 14 print('---main---',os.getpid()) 15 for i in range(10): 16 pool.apply_async(func=Foo,args=(i,),callback=Bar) 17 # callback指向了回调函数(可用于记录日志) 18 # pool.apply(func=Foo,args=(i,)) # 串行 19 pool.apply_async(func=Foo,args=(i,)) # 并行 20 print('end') 21 pool.close() 22 23 # 进程池中进程执行完毕后再关闭,若注释掉,那么程序则直接关闭 24 pool.join()