import multiprocessing
import os, time
def info(title):
print(title)
# time.sleep(1)
print("Module name:", __name__)
print("Parent process id:", os.getppid()) #父进程id
print("Current process id:", os.getpid()) #当前进程id
print("\n\n")
# if __name__ == "__main__": #启动一个子进程
# info("Main process")
# p = multiprocessing.Process(target=info, args=('Child process',))
# p.start()
if __name__ == "__main__": #启动多个子进程(查看结果)
info("Main process")
for i in range(10):
p = multiprocessing.Process(target=info, args=('Child process %s' %i,))
p.start()
注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。
进程间通信
不同进程之间内存是不共享的,要想实现两个进程间的数据交换,有以下方法:
进程队列(Queue)
使用方法跟threading里的queue差不多(进程Queue使用pickle数据传递)
import multiprocessing, time
def put_func(qq):
qq.put([12, None, "hello"])
# time.sleep(2)
# print("put:",qq.qsize())
def get_func(qq):
print(qq.get())
if __name__ == "__main__":
q = multiprocessing.Queue() #创建一个进程Queue对象
puter = multiprocessing.Process(target=put_func,args=(q,)) #将Queue对象传递到新创建的子进程中
puter.start()
geter = multiprocessing.Process(target=get_func, args=(q,))
geter.start()
Pipe
pipe()返回一对连接对象,conn1, conn2代表了pipe的两端。每个对象都有send()和recv()方法。
from multiprocessing import Pipe,Process
import time
# a_conn, b_conn = Pipe()
# a_conn.send(['a', 'f', 'e'])
# print(b_conn.recv())
def f(conn):
time.sleep(2)
conn.send(['a', 'b', 'c'])
def ff(conn):
print(conn.recv())
if __name__ == "__main__":
conn1, conn2 = Pipe()
p1 = Process(target=f, args=(conn2,))
p2 = Process(target=ff ,args=(conn1,))
# p1.daemon = True # 加上daemon属性
# p2.daemon = True
p1.start()
p2.start()
Manager
Python实现多进程间通信的方式有很多种,例如队列,管道等。但是这些方式只适用于多个进程都是源于同一个父进程的情况。如果多个进程不是源于同一个父进程,只能用共享内存,信号量等方式,但是这些方式对于复杂的数据结构,例如Queue,dict,list等,使用起来比较麻烦,不够灵活。
Manager是一种较为高级的多进程通信方式,它能支持Python支持的的任何数据结构。
它的原理是:先启动一个ManagerServer进程,这个进程是阻塞的,它监听一个socket,然后其他进程(ManagerClient)通过socket来连接到ManagerServer,实现通信。
from multiprocessing import Process, Manager
import os
def f(d, l):
d[os.getpid()] = os.getpid()
d[1] = '1'
l.append(os.getpid())
print(l)
if __name__ == "__main__":
with Manager() as manager: #manager = multiprocessing.Manager()
d = manager.dict() ## 生成一个可在多个进程间共享和传递的字典
l = manager.list(range(5)) ##生成一个可在多个进程间共享和传递的列表
p_list = []
for i in range(10):
p = Process(target=f, args=(d, l))
p.start()
p_list.append(p)
for res in p_list:
res.join()
print(d)
print(l)
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。进程池设置最好等于CPU核心数量
进程池中有两个方法:
• apply 串行
• apply_async
from multiprocessing import Process, Pool
import time, os
def Foo(i):
time.sleep(2)
return i+100
def Bar(arg):
print(os.getpid()) #使用的主进程做的回调(os.getpid()值是一样的)
print(arg)
if __name__ == '__main__':
pool = Pool(3) #进程池同时可放3个进程
for i in range(10):
# pool.apply(func=Foo, args=(i,))
pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback回调,func执行完毕后执行回调函数,注意:使用的主进程做的回调
print('end')
pool.close() # 一定要先关闭进程池再join
pool.join() #进程池中的进程执行完毕后再关闭,如果注释,程序就直接关闭了