攻克python3-进程

进程

进程是程序的一段执行过程,是个动态概念,是操作系统调度的最小单位。

multiprocessing模块

Process 类用来描述一个进程对象。创建子进程的时候,只需要传入一个执行函数和函数的参数即可完成 Process 示例的创建。

  star() 方法启动进程

  join() 方法实现进程间的同步,等待所有进程退出。

  close() 用来阻止多余的进程涌入进程池 Pool 造成进程阻塞。

multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

  target 是函数名字,需要调用的函数

  args 函数需要的参数,以 tuple 的形式传入

创建子进程

直接调用

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()

继承式调用

from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name
 
    def run(self):
        print('task <%s> is runing' % self.name)
        time.sleep(2)
        print('task <%s> is done' % self.name)
 
if __name__ == '__main__':
    p=MyProcess('egon')
    p.start()
 
    print('')

与线程一样run方法必须重写

进程间通信

这里介绍只有具有亲缘关系的进程才能进行通信。

进程queue

线程queue共用内存空间
进程queue不共用内存空间,只是通过传递数据来达到进程间通信的目的

from multiprocessing import Process,Queue
import threading,queue

def fun(qq):
    qq.put("wurui")

if __name__ == '__main__':
    q=Queue()
    # q=queue.Queue()
    p=Process(target=fun , args=(q,))
    p.start()
    print(q.get())
    p.join()
View Code

管道通信pipe

from multiprocessing import Process,Pipe

def f(conn):
    conn.send("hello!")

if __name__ == '__main__':
    p_conn,c_conn=Pipe()
    p=Process(target=f,args=c_conn)
    p.start()
    print(p_conn.recv())
    p.join()
View Code

manager

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.

A manager returned by Manager() will support types listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue and Array. For example:

from multiprocessing import Process,Manager
import os

def f(d,l):
    d[os.getpid()]=os.getpid()
    l.append(os.getpid())
    print(l)

if __name__ == '__main__':
    with Manager() as m:
        d=m.dict()
        l=m.list(range(5))
        p_list=[]
        for i in range(10):
            p=Process(target=f,args=(d,l))
            p.start()
            p_list.append(p)
        for j in p_list:
            j.join()
        print(d)
        print(l)
View Code

lock(屏幕锁:防止一个进程未打印完成,另一个进程插入)

def f(l,i):
    l.acquire()
    print("hello",i)
    l.release()

if __name__ == '__main__':
    l=Lock()

    for i in range(10):
        Process(target=f,args=(l,i)).start()
View Code

进程池

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,10几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,这时候进程池Pool发挥作用的时候就到了。

Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

from  multiprocessing import Process, Pool,Lock
import time
import os

'''
如何在进程池中使用进程锁
'''
def Foo(i):
    # l.acquire()
    time.sleep(2)
    print("in process",os.getpid())
    # l.release()
    return i + 100      #返回值由回调函数接收

def Bar(arg):
    print('-->exec done:', arg,os.getpid())

if __name__ == '__main__':
    pool = Pool(processes=3) #允许进程池同时放3入个进程
    # l = Lock()
    print("主进程",os.getpid())
    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调
        #pool.apply(func=Foo, args=(i,)) #串行
        #pool.apply_async(func=Foo, args=(i,)) #并行
    # print('end')
    pool.close()    #先close在join
    pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()
View Code
  • pool.apply_async()用来向进程池提交目标请求。
  • pool.join()是用来等待进程池中的worker进程执行完毕,防止主进程在worker进程结束前结束。但pool.join()必须使用在pool.close()或者pool.terminate()之后。
  • close()terminate()的区别在于close()会等待池中的worker进程执行结束再关闭pool,而terminate()则是直接关闭。
  • result.successful()表示整个调用执行的状态,如果还有worker没有执行完,则会抛出AssertionError异常。    
  • 利用multiprocessing下的Pool可以很方便的同时自动处理几百或者上千个并行操作,脚本的复杂性也大大降低.
posted @ 2018-06-28 11:50  苦行僧PH  阅读(154)  评论(0编辑  收藏  举报