进程

多进程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()能够让其他进程通过代理来控制它

      支持的类型: listdictNamespaceLockRLock, SemaphoreBoundedSemaphoreConditionEventBarrierQueueValue 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)。

 

posted @ 2018-01-20 15:15  ︻◣_蝸犇り~  阅读(120)  评论(0编辑  收藏  举报