Python学习——多进程学习
基本的多进程的使用:
1 from multiprocessing import Process 2 import threading 3 import os 4 5 6 def info(title): 7 print(title) 8 print('module name:', __name__) 9 print('parent process:', os.getppid()) 10 print('process id:', os.getpid()) 11 print("\n\n") 12 13 14 def f(name): 15 info('\033[31;1mfunction f\033[0m') 16 print('hello', name) 17 18 19 if __name__ == '__main__': 20 info('\033[32;1mmain process line\033[0m') 21 #p = threading.Thread(target=f, args=('bob',)) 22 p = Process(target=f, args=('bob',)) #its parent process will be this program ,not pycharm. 23 p.start() 24 p.join()
不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:
Queue
from multiprocessing import Queue
pickle(序列化,实际是把内存的数据放到硬盘上,所以不同的进程可以都可以访问,当然整个过程进行了包装)
1 from multiprocessing import Process, Queue 2 import queue 3 4 def f(q): 5 q.put([42, None, 'hello']) 6 7 8 if __name__ == '__main__': 9 q = Queue() #不出现报错的原因在于,pickle模块实现了对数据的封装(复制一个q进入另一个进程,还有其他后续处理) 10 #q = queue.Queue() #会出现报错,因为两个进程之间不同互通数据。 11 p = Process(target=f, args=(q,)) 12 p.start() 13 print(q.get()) # prints "[42, None, 'hello']" 14 p.join()
Manager
这个是实时共享数据的。
1 from multiprocessing import Process, Manager 2 import os 3 4 def f(d, l): 5 d[1] = os.getpid() #可以利用这个看出来,这个数据是共享的数据 6 d['2'] = 2 7 print(d) 8 d[0.25] = None 9 l.append(os.getpid()) 10 11 print(l) 12 13 if __name__ == '__main__': 14 with Manager() as manager: #Manager可以建立多种进程共享数据 15 d = manager.dict() #生成字典,可在多个进程间共享和传递 16 l = manager.list(range(5)) #生成一个列表,里面预置了0-4,5个值,可在多个进程间共享和传递 17 p_list = [] #主要给下面进行等待所以进程结束的 18 for i in range(10): 19 p = Process(target=f, args=(d, l)) 20 p.start() 21 p_list.append(p) 22 for res in p_list: 23 res.join() 24 25 print(d) 26 print(l)
Lock
多线程的Lock,是为了避免屏幕输出或者其他共用输出出现混乱编码的情况。
但是多进程如果是使用manager来做这个管理就会自动加锁,所以不需要自己管理。
进程池
类似于现场的信号量。
必须注意要先close(),再进行join()
pool.close()
pool.join()
进程池中有两个方法:
- apply
- apply_async
使用方法:
#pool.apply_async(func=Foo, args=(i,), callback=Bar) #这个是异步执行,就是并行;callback,回调,就是执行完Foo后,再执行Bar,
#pool.apply(func=Foo, args=(i,)) #这个是同步执行,就是串行
callback:是利用父进程来进行调用,这样可以提高效率,比如执行完进程之后,连接数据库修改日志的时候;
1 from multiprocessing import Process, Pool,freeze_support 2 import time 3 import os 4 5 def Foo(i): 6 time.sleep(2) 7 print("in process",os.getpid()) 8 return i + 100 9 10 def Bar(arg): 11 print('-->exec done:', arg,os.getpid()) 12 13 if __name__ == '__main__': 14 #freeze_support() 15 pool = Pool(processes=5) #允许进程池同时放入5个进程 16 print("主进程",os.getpid()) 17 for i in range(10): 18 pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调 19 #pool.apply(func=Foo, args=(i,)) #串行 20 #pool.apply_async(func=Foo, args=(i,)) #串行 21 print('end') 22 pool.close() 23 pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()