Python多任务(1.多进程的概念和用法 )

 

1.进程的概念

2.进程的状态:

3.python中的进程包  multiprocessing 

 4.多进程的简单使用

5.获取进程的编号 

6.进程执行带有参数的任务

7.进程的注意点

8. 进程、线程的对比


1.进程的概念

  1.     一个正在执行中的程序或者软件就是一个进程
  2.     一个程序运行起来后,代码+用到的资源称之为进程它是操作系统分配资源的基本单元,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行。
  3.    不仅可以通过线程完成多任务,进程也是可以的
  4. 注意:一个程序运行后至少有一个进程,一个进程默认有一个进程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。

2.进程的状态:

 

3.python中的进程包  multiprocessing 

  • 导入进程包 
  1. import multiprocessing
  2.     multiprocessing模块就是跨平台的多进程模块,提供了一个Process类 代表一个进程对象,这个可以理解为是一个独立的进程,可以执行另外的事情
  3.       进程比线程耗费资源,每开启一个进程,每个子进程里面都有和主进程一样的资源等一些东西。
  •  Process进程类的说明     Process(group,target,name,args,kwargs)
  1. group :指定进程组,目前只能使用None
  2. target:执行的目标任务名
  3. args:以元组的方式给执行任务传参
  4. kwargs:以字典的方式给执行任务传参
  • Process创建的实例对象的常用方法:
  1. start():启动子进程实例(创建子进程)
  2. join():等待子进程执行结束
  3. terminate():不管任务是否完成,立即终止子进程
  • 利用multiprocess模块里面的Process,调用start()方法实现多进程

        对象名 =  multiprocessing.Process(target=函数名)

         对象名.start()  

 4.多进程的简单使用

  • 第一个小例子,同时可以执行两个函数,分别打印1和2
import multiprocessing
import time


def test1():
    for i in range(3):
        print("----1----")
        time.sleep(1)


def test2():
    for i in range(3):
        print("----2----")
        time.sleep(1)


def main():

    p1 = multiprocessing.Process(target=test1)
    #
    p2 = multiprocessing.Process(target=test2)
    '''调用start(),创建了一个子进程'''
    p1.start()   # 主进程有什么,子进程就有什么
    p2.start()

if __name__ == '__main__':
    main()

结果:     一样可以实现多任务。

----1----
----2----
----1----
----2----
----1----

----2----

  • 第二个小例子,分别交给两个子进程执行了。
import time
import multiprocessing

# 跳舞任务
def dance():
    for i in range(3):
        print("跳舞中...")
        time.sleep(0.2)

# 唱歌任务
def sing():
    for i in range(3):
        print("唱歌中...")
        time.sleep(0.2)

# 创建子进程
dance_process = multiprocessing.Process(target=dance)
sing_process = multiprocessing.Process(target=sing)

# 启动进程执行对应的任务
if __name__ == '__main__':
    dance_process.start()
    sing_process.start()

运行结果:

5.获取进程的编号 

  • 获取当前进程编号   (要用到os模块)
os.getpid()
  • 获得当前进程对象      查看当前代码是由哪个进程执行的
multiprocessing.current_process()
  • 获取当前进程的父进程编号   (要用到os模块)
os.getppid()
  • 根据进程编号强制杀死指定进程
os.kill(进程编号, 9)

  • 使用上面的例子,进行查看进程编号等
import os
import multiprocessing
import time


# 获取进程编号
def dance():
    # 获取当前进程(子进程)的编号
    dance_process_id = os.getpid()
    # 获取当前进程对象,查看当前代码是由那个进程执行:
    print("dance_process_id:", dance_process_id, multiprocessing.current_process())
    # 获取当前进程的父进程编号
    dance_process_parent_id = os.getppid()
    print("dance_process的父进程编号是:", dance_process_parent_id)

    for i in range(3):
        print("跳舞中...")
        time.sleep(0.2)
        # 根据进程编号强制杀死指定进程
        os.kill(dance_process_id, 9)


# 获取进程编号
def sing():
    # 获取当前进程(子进程)的编号
    sing_process_id = os.getpid()
    # 获取当前进程对象,查看当前代码是由那个进程执行:
    print("sing_process_id:", sing_process_id, multiprocessing.current_process())
    # 获取当前进程的父进程编号
    sing_process_parent_id = os.getppid()
    print("sing_process的父进程编号是:", sing_process_parent_id)

    for i in range(3):
        print("唱歌中...")
        time.sleep(0.2)
        # 根据进程编号强制杀死指定进程
        os.kill(sing_process_id, 9)




# 启动进程
if __name__ == '__main__':
    # 获取当前进程(主进程)的编号
    main_process_id = os.getpid()
    print("main_process_id:", main_process_id, multiprocessing.current_process())

    # 创建子进程
    dance_process = multiprocessing.Process(target=dance, name="dance_process")
    print("dance_process:", dance_process)
    sing_process = multiprocessing.Process(target=sing, name="sing_process")
    print("sing_process:", dance_process)

    # 启动进程
    dance_process.start()
    sing_process.start()

运行结果:


6.进程执行带有参数的任务

  • 以元组方式传参,元组里面的元素顺序要和函数的参数顺序保持一致
import multiprocessing


# 显示信息的任务
def show_info(name, age):
    print(name, age)


# 以元组方式传参,元组里面的元素顺序要和函数的参数顺序保持一致
sub_process = multiprocessing.Process(target=show_info, args=("李四", 20))

if __name__ == '__main__':
    sub_process.start()
  • 以字典方式传参,字典里面的key要和函数里面的参数名保持一致,没有顺序要求
import multiprocessing


# 显示信息的任务
def show_info(name, age):
    print(name, age)


# 以字典方式传参,字典里面的key要和函数里面的参数名保持一致,没有顺序要求
sub_process = multiprocessing.Process(target=show_info, kwargs={"age": 20, "name": "王五"})

if __name__ == '__main__':
    sub_process.start()

7.进程的注意点

  1. 进程之间不共享全局变量
  2. 主进程会等待所有的子进程执行结束再结束
  3. 创建子进程其实是对主进程资源进行拷贝,子进程其实就是主进程的一个副本
  4. 对应Linux和Mac系统的主进程执行的代码不会进程拷贝,但是对应window系统来说主进程执行的代码会进行拷贝,对应window来说创建子进程的代码如果进程拷贝执行,相当于递归无限制进行创建子进程,会如下报错。
    RuntimeError: 
            An attempt has been made to start a new process before the
            current process has finished its bootstrapping phase.
    
            This probably means that you are not using fork to start your
            child processes and you have forgotten to use the proper idiom
            in the main module:
    
                if __name__ == '__main__':
                    freeze_support()
                    ...
    
            The "freeze_support()" line can be omitted if the program
            is not going to be frozen to produce an executable.
    如何解决windows递归创建子进程,通过判断是否是主模块来解决:
    if __name__ == '__main__':
        '''
            可以把创建进程和启动进程的代码放到这里面
            作用:
                1.防止别人导入文件的时候执行main里面的代码
                2.防止windows系统递归创建子进程
    
        '''
  5. 直接执行的模块就是主模块,那么直接执行的模块里面就应该添加判断是否是主模块的代码

8.实现主进程退出子进程销毁

     因为主进程会等待子进程执行完成之后再退出,如果子进程是一个死循环,主程序也就退不出了

      解决办法:     主进程退出子进程销毁

     让子进程设置为守护主进程,主进程退出子进程销毁,子进程会依赖主进程

  • 进程名.daemon = True 

      可以在启动线程的代码的前面加上     进程名.daemon = True  ,

if __name__ == '__main__':
    sub_process.daemon = True
    sub_process.start()
  • 进程名.terminate()
    退出主进程之前,先让子进程进行销毁
    sub_process.terminate()

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还是那个同伟伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值