Python多任务 - 进程

2021-04-13 15:07:13 浏览数 (1)

了解进程(Process)

对于进程的定义,从不同的角度可以有不同的定义

  • 进程是程序的一次执行
  • 进程是一个程序及其数据在处理机上顺序执行时所发生的活动
  • 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配合调度的一个独立单位

程序是指令、数据及其组织形式的描述,进程是程序的实体

进程是进程实体的运行过程,系统进行资源分配合调度的一个独立单位。

举例说明:

程序:例如 xxx.py 这是程序,是一个静态的。

进程:一个程序运行起来后,代码 用到的资源称之为进程,它是操作系统分配资源的独立单位。

进程的状态

工作中,任务数往往大于 CPU 的核数,即一定有一些任务正在执行,而另外一些任务在等待 CPU 进行执行,因此导致了有了不同的状态

进程状态图

  • 就绪态:运行的条件都已经慢去,正在等在 CPU 执行
  • 执行态CPU 正在执行其功能
  • 等待态:等待某些条件满足,例如一个程序 sleep 了,此时就处于等待态

Python多进程

GIL(Global Interpreter Lock 全局解释器锁):每个线程在执行的过程中都需要先获取 GIL,保证同一时刻只有一个线程可以执行代码。

由于 GIL(全局解释器锁) 的原因,Python中的多线程是 “伪并行” 无法利用 CPU 多核优势,如果想要充分地使用多核 CPU 的资源,在Python中大部分情况需要使用多进程。Python提供了 multiprocessing 模块来实现多进程。

multiprocessing 创建多进程

multiprocessing 模块就是跨平台版本的多进程模块,提供了一个 Process 类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。

2个while循环一起执行

代码语言:javascript复制
# -*- coding:utf-8 -*-
import time
from multiprocessing import Process  # 首先导入Process类


def run_proc():
    """子进程要执行的代码"""
    while True:
        print("----2----")
        time.sleep(1)


if __name__=='__main__':
    p = Process(target=run_proc)  # 传入要执行的目标函数
    p.start()       # 启动进程
    while True:
        print("----1----")
        time.sleep(1)

运行结果如下:

代码语言:javascript复制
----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----
...

说明

  • 创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用 start() 方法启动
Process语法结构
代码语言:javascript复制
Process([group [, target [, name [, args [, kwargs]]]]])

参数

含义

target

表示调用对象,即子进程要执行的任务

args

给target指定的函数传递的参数,以元组的方式传递 如:args=(1,2,'hui',)

kwargs

给target指定的函数传递关键字参数 如:kwargs={'name':'hui','age':18}

name

给进程设定一个名字,可以不设定

group

指定进程组

Process对象的常用方法

方法

作用

start()

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

is_alive()

判断进程子进程是否还在活着

join([timeout])

是否等待子进程执行结束,或等待多少秒

terminate()

不管任务是否完成,立即终止子进程

Process对象的常用属性

  • name:当前进程的别名,默认为 Process-N,N为从1开始递增的整数
  • pid:当前进程的pid(进程号)
给子进程指定的函数传递参数
代码语言:javascript复制
# -*- coding:utf-8 -*-
import os
from time import sleep
from multiprocessing import Process


def run_proc(name, age, **kwargs):
    for i in range(10):
        print('子进程运行中,name= %s,age=%d ,pid=%d...' % (name, age, os.getpid()))
        print(kwargs)
        sleep(0.2)

        
def main():
    p = Process(target=run_proc, args=('test',18), kwargs={"m":20})
    p.start()
    sleep(1)    # 1秒中之后,立即结束子进程
    p.terminate() # 终止子进程
    p.join()  
    
    
if __name__=='__main__':
    main()

运行结果:

代码语言:javascript复制
子进程运行中,name= test,age=18 ,pid=45097...
{'m': 20}
子进程运行中,name= test,age=18 ,pid=45097...
{'m': 20}
子进程运行中,name= test,age=18 ,pid=45097...
{'m': 20}
子进程运行中,name= test,age=18 ,pid=45097...
{'m': 20}
子进程运行中,name= test,age=18 ,pid=45097...
{'m': 20}

继承Process类创建多进程

创建进程的方式还可以使用类的方式,可以自定义一个类,继承 Process 类,重写run方法,每次实例化这个类的时候,就等同于实例化一个进程对象

代码语言:javascript复制
import time
from multiprocessing import Process
 
    
# 定义进程类
class ClockProcess(Process):
 def __init__(self,interval):
  super().__init__(self) # 记得加载Process类的__init__()方法
  self.interval = interval
        
 def run(self):
  print('子进程开始执行的时间:{}'.format(time.ctime()))
  time.sleep(self.interval)
  print('子进程结束的时间:{}'.format(time.ctime()))
 

def main():
    # 创建子进程睡眠两秒
 p = ClockProcess(2)
 # 调用子进程
 p.start()
    # 等待子进程结束
 p.join()
 print('主进程结束')
    
    
if __name__=='__main__':
 main()

运行结果

代码语言:javascript复制
子进程开始执行的时间:Sat Oct  3 23:21:20 2020
子进程结束的时间:Sat Oct  3 23:21:22 2020
主进程结束

继承 Process 类,重写run方法,实例化的对象调用 start() 方法就会执行 run() 方法的代码

进程间不共享全局变量

代码语言:javascript复制
# -*- coding:utf-8 -*-
import os
import time
from multiprocessing import Process


nums = [11, 22]


def work1():
    """子进程要执行的代码"""
    print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums))
    for i in range(3):
        nums.append(i)
        time.sleep(1)
        print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums))

        
def work2():
    """子进程要执行的代码"""
    print("in process2 pid=%d ,nums=%s" % (os.getpid(), nums))

    
def main():
    p1 = Process(target=work1)
    p1.start() # 子进程开启
    p1.join() # 等待子进程执行结束

    p2 = Process(target=work2)
    p2.start()
    
    
if __name__ == '__main__':
    main()

运行结果:

代码语言:javascript复制
in process1 pid=11349 ,nums=[11, 22]
in process1 pid=11349 ,nums=[11, 22, 0]
in process1 pid=11349 ,nums=[11, 22, 0, 1]
in process1 pid=11349 ,nums=[11, 22, 0, 1, 2]
in process2 pid=11350 ,nums=[11, 22]

说明: p1 进程往 num 列表添加的元素,与 p2 进程不共享,p2 进程打印的还是原来的 num[11, 12]

Python多线程、进程对比

对比方式

线程

进程

Python模块

threading

multiprocessing

开启方式

threading.Thread() 继承 Thread 类

multiprocessing.Process() 继承 Process 类

共享全局变量

共享

不共享

0 人点赞