Python多进程
1.Process类
Process类是用来创建进程的
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)其中group应该永远为空,它的存在仅仅是与threading.Thread兼容,threading,Thread也有一个group的参数,不过现在也没有使用,保留到以后线程组实现了以后再用。target,传入一个函数这样的可调用对象,执行run方法的时候会执行这个函数。name就是定义进程的名字,如果这个参数不定义,则默认名字为Process-x (x是序号)。args是个参数元组,kwargs是个字典,都是传给target作为参数。参数daemon可以设置进程是否是守护进程,如果为空,这个参数将会从父进程继承。当一个进程退出的时候,它会尝试去终止所有的daemon子进程,一个daemon进程不允许创建子进程,否则的话当父进程退出的时候这些子进程就变为孤儿进程了.daemon进程的使用场景是:需要一个始终运行的进程,用来监控其他服务的运行情况,或者发送心跳包或者类似的东西,创建了这个进程以后就不用管他了,它会随着主进程的退出而退出。进程创建以后,可以通过访问属性的方式进行设置:
p = multiprocessing.Process(target = worker, args = (3,))
p.daemon = True
存在以下接口:run()、start()、join()、is_alive()、terminate() ,接口相对都比较简单,类似于线程,下面是一个创建进程的简单例子
import multiprocessing import time def worker(interval): print("CCD") if __name__ == "__main__": p = multiprocessing.Process(target = worker, args = (3,) ,name = "ccd") print("p.name:",p.name) p.start()
2.Lock(锁)
Lock.acquire () 获得锁 Lock.release() 释放锁,RLock是可重入锁 RLock.acquire()获得锁 RLock.release() 释放锁
3.Semaphore(信号量)
Semphore,是一种带计数的同步机制,当调用release时,增加计算,当acquire时,减少计数,当计数为0时,自动阻塞,等待release被调用。可以用来控制对共享资源的访问数量,例如池的最大连接数。例子如下:
import multiprocessing import time def worker(s, i): s.acquire() print(multiprocessing.current_process().name + "acquire"); time.sleep(i) print(multiprocessing.current_process().name + "release "); s.release() if __name__ == "__main__": s = multiprocessing.Semaphore(2) for i in range(5): p = multiprocessing.Process(target=worker,args=(s,i)) p.start()
结果如下: 我们信号量初始化为2,所以创建的第三个进程没法执行,只能阻塞,直到有进程释放信号量。
Process-4acquire Process-3acquire Process-3release Process-2acquire Process-4release Process-1acquire Process-1release Process-5acquire Process-2release Process-5release
4.Event(事件)
类似于线程的Event,主要接口有set()、clear()、wait()
5.Pipe(管道)
Pipe方法返回(conn1,conn2)这样一组Connetion对象,Pipe方法有duplex参数,如果duplex参数为True(默认值),那么这个管道是全双工模式,也就是说conn1和conn2均可收发。duplex为False,conn1只负责接受消息,conn2只负责发送消息。
例子:
import multiprocessing import time def proc1(pipe): while True: for i in range(5): print("send: %s" % (i)) pipe.send(i) time.sleep(1) def proc2(pipe): while True: print("rev:", pipe.recv()) time.sleep(1) if __name__ == "__main__": pipe = multiprocessing.Pipe() p1 = multiprocessing.Process(target=proc1, args=(pipe[0],)) p2 = multiprocessing.Process(target=proc2, args=(pipe[1],)) p1.start() p2.start() p1.join() p2.join()
结果如下:
send: 0 rev: 0 send: 1 rev: 1 send: 2 rev: 2
....
6.Queue(队列)
Queue是一种进程安全的共享数据结构,进程之间可以使用队列进行数据共享,队列是由管道和一些锁/信号量来实现的,当一个进程将数据放入队列中,就会起一个线程将对象从buffer中放到pipe中来。主要的接口有put()、get()
对于put()接口是将元素放入队列中,其中有两个可选参数block,timeout。如果block为True同时timeout为none(默认值),则会一直阻塞直到队列中空闲。如果timeout不为none,
是个正数,则会阻塞timeout秒,如果超时的时候队列还是满的,则就抛出queue.Full异常。如果block为false,如果队列空闲,则put操作直接将元素放入队列中,如果队列满,则直接抛出queue.Full异常。简单的说,就是put操作将元素放入队列中,如果采用非阻塞方式,队列有空闲则直接放入,否则抛出异常。而阻塞方式,如果队列满了,还会阻塞等待,如果指定了超时时间,则只会阻塞超时时间这么久,否则一直阻塞下去,直到队列有空闲
get()接口是从队列中读取并移除一个元素, 它也有block,timeout两个数据。只不过是在队列为空的时候阻塞,通过block参数决定取数据的时候队列为空的情况阻塞不阻塞。
import multiprocessing def writer_proc(q): try: q.put(1, block = False) except: pass def reader_proc(q): try: print q.get(block = False) except: pass if __name__ == "__main__": q = multiprocessing.Queue() writer = multiprocessing.Process(target=writer_proc, args=(q,)) writer.start() reader = multiprocessing.Process(target=reader_proc, args=(q,)) reader.start() reader.join() writer.join()
结果如下:
1