进程
多进程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)。

浙公网安备 33010602011771号