一、多进程
多进程合适计算密集型的应用,以下给出python中两个模块:subprocess和multiprocessing。
1、subprocess
subprocess是
用来执行其他的可执行程序的,即执行外部命令。 它是os.fork() 和 os.execve() 的封装。
它启动的进程不会把父进程的模块加载一遍。使用subprocess的通信机制比较少,通过管道或者信号机制。
简而言之,使用subproces来为外部的可执行程序创建多进程比较方便。
具体的代码如下:
import subprocess
import os
with open("pair.txt") as pair:
s = []
for line in pair:
line_str = line.split()
print(line_str[0], line_str[1])
print("computing the Home between %s and %s"%(line_str[0], line_str[1]))
pro = subprocess.Popen(['./Homo2.exe', line_str[0], line_str[1]])
s.append(pro)
if len(pro) >= 4:
s[0].wait()
s.pop(0)
multiprocessing用来执行python的函数,它启动的进程会重新加载父进程的代码。可以通过Queue、Array、Value等对象来通信。简而言之,当我们需要为python自己的函数创建多进程的时候,使用multiprocessing比较方便。
具体代码如下:
import multiprocessing import time def run(name): time.sleep(2) print('%s is sleeping...'%name) def main(): for i in range(10): p = multiprocessing.Process(target=run, args=('Bob %s'%i,)) p.start() if __name__ == '__main__': main()
二、进程间的通信
1、由于进程之间PCB是相互独立的,因此各个进程之间想要实现相互通信的功能,就需要一些通信机制,常见的通信机制有:管道(pipe)、消息队列(message queue)、
共享内存(shared memory)和套接字(socket)。
2.管道(pipe)
(1)管道有双向的,也有单向的;
(2)管道的创建:
pipe = multiprocessing.Pipe() 双向的管道;
pipe = multiprocessing.Pipe(duplex=False) 双向的管道,pipe[0]为接收端,pipe[1]为发送端;(3)双管道代码
from multiprocessing import Process,Pipe def proc1(pipe): s = 'Hello World' pipe.send(s) def proc2(pipe): while True: print(pipe.recv()) def main(): pipe = Pipe() p1 = Process(target=proc1, args=(pipe[0],)) p2 = Process(target=proc2, args=(pipe[1],)) p1.start() p2.start() p1.join() p2.join() if __name__ == '__main__': main()
(4)单管道代码
from multiprocessing import Process,Pipe def proc1(pipe): s = 'Hello World' pipe.send(s) def proc2(pipe): while True: print(pipe.recv()) def main(): pipe = Pipe(duplex=False) p1 = Process(target=proc1, args=(pipe[1],)) #pipe[1]为发送端 p2 = Process(target=proc2, args=(pipe[0],)) #pipe[0]为接收端 p1.start() p2.start() p1.join() p2.join() if __name__ == '__main__': main()
3、队列(queue)
(1)代码实现
from multiprocessing import Process,Queue,Lock def add(q,a,b,lock): lock.acquire() li = range(a,b) lock.release() q.put(li) for item in li: print(item) def main(): lock = Lock() L = [1, 2, 3] q = Queue() p1 = Process(target=add, args=(q,10,20,lock)) p2 = Process(target=add, args=(q,20,30,lock)) p1.start() p2.start() p1.join() p2.join() L += q.get() L += q.get() print(L) if __name__ == '__main__': main()
(2)熟悉使用队列的方法,例如:q.get(),q.put()等函数
4、共享内存(manager)
(1)Manager是专门用作数据共享的,其支持的数据类型有很多,例如:Value、Array、List、Queue、dict等
(2)代码实现:利用manager共享dict和list
from multiprocessing import Process, Manager import os def run(dic, l): dic[os.getpid()] = os.getpid() #字典 l.append(os.getpid()) #列表 if __name__ == '__main__': with Manager() as manager: d = manager.dict() l = manager.list(range(5)) p_list = [] for i in range(10): p = Process(target=run, args=(d,l)) p.start() p_list.append(p) for p in p_list: p.join() print(l) print(d)
5、套接字(socket)
利用套接字实现进程之间的通信,常见的例子是:TCP/IP中的服务器端和客户端,这里不再赘述,请参见前面的博客。