进程
多进程multiprocessing
多线程适合场景:不适合cpu操作密集型的任务,适合io密集型的任务
多进程适合场景:适合cpu操作密集型的任务
进程启动方法
from multiprocessing import Process import time def f(name): time.sleep(2) print("hello",name) if __name__ == "__main__": p = Process(target=f,args=("bob",)) p.start() p.join() # 等待进程执行完成
获取进程id(每个进程都是由父进程启动的)
1 from multiprocessing import Process 2 import os 3 4 def info(title): 5 print(title) 6 print('module name:', __name__) 7 print('parent process:', os.getppid()) # os.getppid()查父进程pid 8 print('process id:', os.getpid()) # os.getpid()查当前进程pid 9 print("\n\n") 10 11 def f(name): 12 info('\033[31;1mfunction f\033[0m') 13 print('hello', name) 14 15 if __name__ == '__main__': 16 info('\033[32;1mmain process line\033[0m') 17 p = Process(target=f, args=('bob',)) 18 p.start() 19 p.join()
进程间通讯
不同进程间内存是不共享的,要实现两个进程间的数据交换
Queues 队列(父进程与子进程之间队列通信通过pickle序列化与反序列化)
1 from multiprocessing import Process, Queue 2 3 def f(q): 4 q.put([42, None, 'hello']) 5 6 if __name__ == '__main__': 7 q = Queue() # 队列对象 8 p = Process(target=f, args=(q,)) # 父进程与子进程其实不是同一个队列,传给子进程时实际上是克隆了一份 9 p.start() 10 print(q.get()) # prints "[42, None, 'hello']" 11 p.join()
Pipes 管道:返回一对连接对象(通过send与recv方式存放、提取数据)
同一时刻有多个进程或线程同时读或者写时数据可能会损坏
from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello']) conn.close() if __name__ == '__main__': parent_conn, child_conn = Pipe() # 相当于电话的两端,无论哪个传给子进程都可以,两边都可以进行正常接收、发送操作 p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # prints "[42, None, 'hello']" p.join()
Managers:Managers()能够让其他进程通过代理来控制它
支持的类型: list
, dict
, Namespace
, Lock
, RLock
, Semaphore
, BoundedSemaphore
, Condition
, Event
, Barrier
, Queue
, Value
and Array
.
1 from multiprocessing import Process, Manager 2 3 def f(d, l): 4 d[1] = '1' # 子进程字典中写入数据 5 d['2'] = 2 6 d[0.25] = None 7 l.append(1) # 子进程列表中写入数据 8 print(l) 9 10 if __name__ == '__main__': 11 with Manager() as manager: 12 d = manager.dict() # 创建一个可以进程共享的字典 13 14 l = manager.list(range(5)) # 创建一下可以进程共享的列表 15 p_list = [] 16 for i in range(10): 17 p = Process(target=f, args=(d, l)) 18 p.start() 19 p_list.append(p) 20 21 for res in p_list: # 等待所有进程执行完 22 res.join() 23 24 print(d) # 主进程读取字典中数据 25 print(l) # 主进程读取列表中数据
进程同步
from multiprocessing import Process, Lock def f(l, i): l.acquire() try: print('hello world', i) finally: l.release() if __name__ == '__main__': lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start()
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么进程就会等待,直到进程池中有可用进程池为止
1 from multiprocessing import Process,Pool 2 import time 3 import os 4 5 def Foo(i): 6 time.sleep(2) 7 print("current pid",os.getpid()) 8 return i+100 9 10 def Bar(arg): 11 print('-->exec done:',arg) 12 13 pool = Pool(5) # 允许进程池中同时放入5个进程,其他的都是挂起状态 14 15 for i in range(10): 16 # callback=回调,前面没做完就不执行callback,执行完了就执行callback,回调是父进程调用的 17 # 如果子进程回调的话会造成多个连接的情况,父进程每执行完回调性能更好 18 pool.apply_async(func=Foo, args=(i,),callback=Bar) # 异步执行 19 #pool.apply(func=Foo, args=(i,)) # 同步执行,相当于串行 20 21 print('end') 22 pool.close() 23 pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭(apply_async)。