• python通过多进程实行多任务


    #原创,转载请联系

      

        在开始之前,我们要知道什么是进程。道理很简单,你平时电脑打开QQ客户端,就是一个进程。再打开一个QQ客户端,又是一个进程。那么,在python中如何用一篇代码就可以开启几个进程呢?通过一个简单的例子来演示:

    import multiprocessing
    import time
    
    
    def task1():
        while True:
            time.sleep(1)
            print("I am task1")
    
    def task2():
        while True:
            time.sleep(2)
            print("I am task2")
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task1)  # multiprocessing.Process创建了子进程对象p1
        p2 = multiprocessing.Process(target=task2)  # multiprocessing.Process创建了子进程对象p2
        p1.start()  # 子进程p1启动
        p2.start()  # 子进程p2启动
        print("I am main task")  # 这是主进程的任务

    输出结果:
    I am main task
    I am task1
    I am task2
    I am task1
    I am task1
    I am task2
    I am task1
    I am task1
    I am task2
    ...
    ...

        可以看到子进程对象是由multiprocessing模块中的Process类创建的。除了p1,p2两个被创建的子进程外。当然还有主进程。主进程就是我们从头到尾的代码,包括子进程也是由主进程创建的。

    注意的点有:

    1.首先解释一下并发:并发就是当任务数大于cpu核数时,通过操作系统的各种任务调度算法,实现多个任务“一起”执行。(实际上总有一些任务不在执行,因为切换任务相当快,看上去想同时执行而已。)

    2.当是并发的情况下,子进程与主进程的运行都是没有顺序的,CPU会采用时间片轮寻的方式,哪个程序先要运行就先运行哪个。

    3.主进程会默认等待所有子进程执行完毕后,它才会退出。所以在上面的例子中,p1,p2子进程是死循环进程,主进程的最后一句代码print("I am main task")虽然运行完了,但是主进程并不会关闭,他会一直等待着子进程。

    4.主进程默认创建的是非守护进程。注意,结合3.和5.看。

    5.但是!但是!如果子进程是守护进程的话,那么主进程运行完最后一句代码后,主进程会直接关闭,不管你子进程运行完了没有!

     -------------------------------------------------------------------------------------------------------------我是一条分割线------------------------------------------------------------------------------------------------------------------------------------

    不相信?

    那我们来测试下

    import multiprocessing
    import time
    
    
    def task1():
        while True:
            time.sleep(1)
            print("I am task1")
    
    def task2():
        while True:
            time.sleep(2)
            print("I am task2")
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task1)
        p2 = multiprocessing.Process(target=task2)
        p1.daemon = True  # 设置p1子进程为守护进程
        p2.daemon = True  # 设置p2子进程为守护进程
        p1.start()
        p2.start()
        print("I am main task")

    输出结果:
    I am main task

    输出结果是不是有点奇怪。为什么p1,p2子进程都没有输出的?

    让我们来整理一下思路:

    1.创建p1,p2子进程

    2.设置p1,p2子进程为守护进程

    3.p1,p2子进程开启

    4.p1,p2子进程代码里面都有休眠时间,所以cpu为了不浪费时间,先做主进程后续的代码。

    5.执行主进程后续的代码,print("I am main task")

    6.主进程后续的代码执行完成了,所以剩下的子进程是守护进程的,全都要关闭了。但是,如果主进程的代码执行完了,有两个子进程,一个是守护的,一个非守护的,怎么办呢?其实,他会等待非守护的那个子进程运行完,然后三个进程一起关闭。

    7.p1,p2还在休眠时间内就被终结生命了,所以什么输出都没有。

    里面涉及到两个知识点:

    1.当主进程结束后,会发一个消息给子进程(守护进程),守护进程收到消息,则立即结束

    2.CPU是按照时间片轮寻的方式来运行多进程的。哪个合适的哪个运行,如果你的子进程里都有time.sleep。那我CPU为了不浪费资源,肯定先去干点其他的事情啊。

    那么,守护进程随时会被中断,他的存在意义在哪里的?

    其实,守护进程主要用来做与业务无关的任务,无关紧要的任务,可有可无的任务,比如内存垃圾回收,某些方法的执行时间的计时等。

    -------------------------------------------------------------------------------------------------------------我是一条分割线------------------------------------------------------------------------------------------------------------------------------------

    虽然知道怎么简单的创建子进程,但是如果要创建的子进程要传入参数,应该怎么操作呢?

    import multiprocessing
    
    
    def task(a,b,*args,**kwargs):
        print("a")
        print("b")
        print(args)
        print(kwargs)
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task,args=(1,2,3,4,5,6),kwargs={"name":"chichung","age":23})
        p1.start()
        print("主进程已经运行完最后一行代码啦")

    输出:

    主进程已经运行完最后一行代码啦
    a
    b
    (3, 4, 5, 6)
    {'name': 'chichung', 'age': 23}

    子进程要运行的函数需要传入变量a,b,一个元组,一个字典。我们创建子进程的时候,变量a,b要放进元组里面,task函数取的时候会把前两个取出来,分别赋值给a,b了。

    -------------------------------------------------------------------------------------------------------------我是一条分割线------------------------------------------------------------------------------------------------------------------------------------

    创建的子进程有几个常用的方法:

    p.start 开始执行子线程
    p.name 查看子进程的名称
    p.pid 查看子进程的id
    p.is_alive 判断子进程是否存活
    p.join(timeout)

    阻塞主进程,当子进程p运行完毕后,再解开阻塞,让主进程运行后续的代码

    如果timeout=2,就是阻塞主进程2s,这2s内主进程不能运行后续的代码。过了2s后,就算子进程没有运行完毕,主进程也能运行后续的代码

    p.terminate 终止子进程p的运行
    import multiprocessing
    
    
    def task(a,b,*args,**kwargs):
        print("a")
        print("b")
        print(args)
        print(kwargs)
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task,args=(1,2,3,4,5,6),kwargs={"name":"chichung","age":23})
        p1.start()
        print("p1子进程的名字:%s" % p1.name)
        print("p1子进程的id:%d" % p1.pid)
        p1.join()
        print(p1.is_alive())
    
    输出:
    p1子进程的名字:Process-1
    p1子进程的id:19345
    a
    b
    (3, 4, 5, 6)
    {'name': 'chichung', 'age': 23}
    False

    这个没什么好说的,自己体会一下......

    -------------------------------------------------------------------------------------------------------------我是一条分割线------------------------------------------------------------------------------------------------------------------------------------

    进程之间是不可以共享全局变量的,即使子进程与主进程。道理很简单,一个新的进程,其实就是占用一个新的内存空间,不同的内存空间,里面的变量肯定不能够共享的。实验证明如下:

    import multiprocessing
    
    g_list = [123]
    
    
    def task1():
        g_list.append("task1")
        print(g_list)
    
    
    def task2():
        g_list.append("task2")
        print(g_list)
    
    
    def main_process():
        g_list.append("main_processs")
        print(g_list)
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task1)
        p2 = multiprocessing.Process(target=task2)
        p1.start()
        p2.start()
        main_process()

    输出:
    [123, 'main_processs']
    [123, 'task1']
    [123, 'task2']

    一针见血了吧,哈哈~

    ----------------------------------------------------------------------------------------------------------我是一条结束线,谢谢观看~-----------------------------------------------------------------------------------------------------------------------

  • 相关阅读:
    jquery插件之文字无缝向上滚动
    jquery插件之tab标签页或滑动门
    jquery插件之表格隔行变色并鼠标滑过高亮显示
    jquery过滤器之:contains()、.filter()
    css3动画在动作结束时保持该状态不变的解决办法
    CSS3两个动画顺序衔接播放
    css去掉使用bootstrap框架后打印网页时预览效果下的超链接
    R in action读书笔记(13)第十章 功效分析
    Python学习 Day 7 面向对象 类和实例 访问限制
    R in action读书笔记(12)第九章 方差分析
  • 原文地址:https://www.cnblogs.com/chichung/p/9532962.html
Copyright © 2020-2023  润新知