进程
进程,至少包含一个线程
IO操作不占用CPU,从内存,硬盘,网络读数据这都叫IO操作
计算才占用CPU python多线程,不适合CPU密集操作性任务,适合IO操作密集型任务
创建新进程需要对其父进程进行一次克隆
一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程
多进程multiprocessing
import multiprocessing,threading import time def run(name): time.sleep(1) print("hello",name) t=threading.Thread(target=thread_run) # 进程里面实现多线程 t.start() def thread_run(): print(threading.get_ident()) if __name__=="__main__": for i in range(10): p=multiprocessing.Process(target=run,args=('jim %s'%i,)) p.start() # p.join()
# -*-coding:utf-8-*- # Author:sunhao import os,multiprocessing def info(): print("父进程",os.getppid()) print("进程id",os.getpid()) print(" ") def f(): info() if __name__ == '__main__': #子进程都是由父进程生成的 info() p=multiprocessing.Process(target=f) p.start()
进程间通讯
不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:
1.Queues
import multiprocessing def f(qq): qq.put([42,None,'hello']) if __name__=='__main__': que=multiprocessing.Queue() p=multiprocessing.Process(target=f,args=(que,)) # 将父进程que传给子进程 中间通过pickle序列化 实际上是有两个que p.start() print(que.get())
2.Pipes管道
# -*-coding:utf-8-*- # Author:sunhao import multiprocessing def f(conn): conn.send([42,None,'lily1']) conn.send([42, None, 'lily2']) print("from child") #print(conn.recv()) conn.close() if __name__ == '__main__': parent_conn,child_conn = multiprocessing.Pipe() #生成一个管道实例 两个返回变量 相当于电话线的两头 这头传递到那头 p=multiprocessing.Process(target=f,args=(child_conn,)) p.start() print(parent_conn.recv()) print(parent_conn.recv()) parent_conn.send("from parent") p.join()
进程间共享数据Manager
# -*-coding:utf-8-*- # Author:sunhao import multiprocessing,os def f(d,l): d[os.getpid()]=os.getpid() l.append(os.getpid()) if __name__=='__main__': with multiprocessing.Manager() as manager: d=manager.dict() #生成一个字典 可在多个进程间共享和传递 l=manager.list(range(5)) #生成一个列表 可在多个进程间共享和传递 p_list=[] for i in range(10): p=multiprocessing.Process(target=f,args=(d,l)) p.start() p_list.append(p) for res in p_list: res.join() print(d) 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() #要把lock当参数 传进去
进程池
同一时间有几个进程在cpu上运行
线程没有线程池的原因是线程的开销太小,而启动进程的开销比较大
进程池中有两个方法:
- apply 串行
- apply_async 并行 里边有个回调函数
# -*-coding:utf-8-*- # Author:sunhao import multiprocessing import time,os def Foo(i): time.sleep(2) print("in process",os.getpid()) return i+100 def bar(arg): print("exec done",arg,os.getpid()) if __name__=='__main__': pool = multiprocessing.Pool(3) #允许进程池里放入5个进程 print("主程序pid",os.getpid()) for i in range(10): # pool.apply(func=Foo,args=(i,)) #apply串行 apply_async并行 # pool.apply_async(func=Foo, args=(i,)) pool.apply_async(func=Foo, args=(i,),callback=bar) #callback ==回调 回调是等一个进程执行完毕后 在执行callback的函数 print("done") pool.close() #先关闭再join pool.join() #进程池中进程执行完毕后在关闭,如果注释,那么程序直接关闭