Python之进程

一:什么是进程

    当代码编译完成,在没有运行时称之为程序。正在运行着的代码,称之为进程。

二:进程的创建

    1:fork

    2:  multiprocessing

   

三:Fork

     fork 为unix环境下创建子进程,封装在OS模块中。

    例1:fork()创建子进程


   代码讲解:当程序运行至os.fork()会创建出一个子进程,然后复制父进程的所有信息到子进程中,即父进程与子进程均打印一次"--test--"

    例2:fork()返回值


    代码讲解:当程序运行至os.fork()时,会创建一个子进程,并且返回一个非0的值,而此时父进程的返回的值为0。

    例3:进程PID


    代码讲解:os.getpid() 获取当前进程的PID, os.getppid()获取其子进程的PID。

    例4:多进程修改全局变量


    代码讲解:多进程中,每个进程中所有的数据(包括变量)都各自拥有一份,互相不影响

多次Fork说明:


    子父进程的运行顺序没有规律,完全取决于操作系统的算法



四:multiprocessing

    由于fork只能在unix上运行,在windows上无法运行,而Python为跨平台语言,即在引进multiprocessing模块。

    例1:Process


    代码讲解: 其中使用Process创建一个实例子进程,用start()方法启动,其中join()方法可以等待子进程结束后再运行后续代码,通常用于进程间的同步。

Process语法结构:

  Process([group[,target[,name[,args.[kwargs]]]])

        target:表示这个进程实例所调用的对象

        args:表示调用对象的位置参数元组

        kwargs:表示调用对象的关键字数字典

        name :为当前进程实例别名

        group:大多数情况下用不到


Process常用方法:

        is_alive():判断进程实例是否还在执行

        join([timeout]):是否等待进程实例执行结束,或等待多少秒

       start():启动进程实例(创建子进程)

       run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法

        terminate():不管任务是否完成,立即终止 

    例2:Processs


    代码解释: 其中运行至“test = Process(target=Tets_Process,args=(5,))”时,创建一个子进程实例,且通过args将5以元组的形式传递给函数中,"test.start()":启动子进程,“test.join(3)”让子进程堵塞3秒,先运行后续代码。


    例3:创建Process子类,调用run()方法


    代码讲解:NewProcess继承Process类方法,当创建test实例对象事,并没有传对应的方法,会自动调用实例对象中的run()方法。


Pool进程池

        当需要创建的子进程数量不多时,可以直接使用multiprocessing中的Process动态生成多个进程,但如果上百进程,则可以使用multiprocessing模块中Pool方法; Pool初始化时,可以指定一个最大的进程数,当有新的请求提交到Pool中时,如果池还没满,那么就会创建一个新的进程用来执行请求,但如果池中的进程已经达到指定的最大值,那么该请求就会等待,知道池中有进程结束,才会有新的进程执行。

        例4:Pool进程池


    代码解释:当代码运行到"po = Pool(2)"时,初始化进程池,且最大进程池为2;for循环,通过apply_async(workd,(i,))创建worker子进程实例,“po.close()”关闭Pool进程池,使其不在接受新任务; join()主进程堵塞,等待子进程的退出。由于进程池最大为2,急运行结果需要依次排队等待进程。


Pool常用方法:

    apply_async(func[,args[,kwds]]]):使用非阻塞调用func,args为传递给func的参数列表,kwds为传递给func的参数列表

    apply(func[,args[,kwds]]):使用阻塞方法调用func

    close():关闭Pool,使其不再接受新的任务

    terminate():不管任务是否完成,立即终止

    join():主进程阻塞,等待子进程退出,必须在close或terminate之后使用

    

    例5:Pool堵塞试进程


    代码解说: Pool非阻塞试进程和阻塞试进程的区别在于,添加进程是否使用apply_async与apply, 非阻塞试为最大进程池并行,阻塞为,每次等待子进程运行完成之后,运行下一个子进程。


Queue进程间通信:

    Queue的常用方法:

        Queue.qsize():返回当前队列包含的消息数量;

        Queue.empty():如果队列为空,返回True,反正False

        Queue.full():如果队列满了,返回True,反正False

        Queue.get([block[,timeout]]):获取队列中一条消息,然后将其从队列中移除;block默认为True,

          (1)如果True使用默认值,且没有设置timeout,消息队列为空,此时程序会被阻塞(停在读取状态),直到消息队列读到消息为止,如果设置了timeout,则会等待timeout秒,若还未读到消息,则会抛出Queue.Empty异常。如果设置block为False,消息队列如果为空,则会立刻抛出Queue.Empty异常,

          (2)如果block的值为False队列为空,则会立马抛出异常

        Queue.get_nowait():相当于Queue.get(False)

        Queue.put(itme,[block[,timeout]):将itme信息写入队列,block默认值为True

            (1)如果True使用默认值,且没有设置timeout时间,若消息队列已满,此次程序会被阻塞(停在写入状态),直到队列空闲为止,若设置了timeout时间,则会等待timeout秒,若此时还没有空间,则会抛出Queue.Full异常。

           (2)如果使用False,且没有设置timeout时间,若消息队列已满,则会立即抛出异常。

        Queue.put_nowait():等价于Queue.put(False)

    例6:Queue队列,先进先出


    代码解说:使用Queue()创建一个无限制队里,使用Process创建两个实例子进程,通过if判断队列是否为空或爆满状态,来往队列中put和get.

    例7:进程池中的Queue


    代码解说:Queue在进程池中使用,需要使用Manager().Queue()进行初始化, 在导入模块时需要导入Manager()


多中方式的比较:

    1: 在unix系统上,可以使用fork创建子进程,windows上不能使用fork

    2:Process适用于数量较少的子进程创建

    3:Pool适用于数量较多,或不确定子进程数时使用的进程池。

    4:进程之间的通信使用Queue

    5:进程池之间的通信,需要先使用Manager().Queue()对队里进行初始化

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值