多进程

重点源码

class Process():
    name: str  --------------name名字必须是字符串
    daemon: bool
    pid: Optional[int]
    exitcode: Optional[int]
    authkey: bytes
    sentinel: int

易错

不同于深拷贝,进程的空间隔离,主进程和子进程中的不可变元素,除了数字地址是一样的,像字符串等的不遵循小数据池原理

1. 进程创建的两种方式

1. 第一种函数方式

from multiprocessing import Process
import time

def task(name):   # 这个变量名可以改变,与下边对应即可
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is done")

if __name__ == "__main__":
    #在Windows环境下,开启进程必须在__name__ == "__main__"下面
    #此模块与windows某些地方有冲突
    print(666)
    p = Process(target=task,args=("太白",))  #args必须接受一个元祖
    p.start()
    # 只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了,
    # 将p这个进程放进去(copy主进程),然后让CPU去执行
    #只复制了if条件语句的上边部分
    print("==主")
  • 注意
    1. task函数名可以改变,与下边对应即可
    2. Windows环境下,开启进程必须在测试端口
    3. args传的值必须以元组形式,并且传的值要传的值一一对应
    4. p处只是提示操作系统开辟子进程,然后就继续执行了
    5. 子进程复制的只是if语句上边的内容

2. 第二种执行类方法

from multiprocessing import Process
import time

class MyProcess(Process):  # 必须继承Process,类名可以换
    
    def __init__(self,name):
        super().__init__()  #必须继承父类的__init__方法
        #原因在于父类的init还封装着别的参数,必须继承
        self.name = name

    def run(self):
        #必须要写成run方法,改了名字默认继承父类,pass,结果就只执行主进程
        print(f"{self.name} is running")
        time.sleep(2)
        print(f"{self.name} is done")

if __name__ == "__main__":
    p = MyProcess("太白")
    p.start()
    print("==主")

注意

  1. 此类必须继承Process
  2. 传值情况下必须继承父类的__init__方法
  3. 类方法必须是run,如果改了名字只会执行父类
  4. self.name 默认等于 MyProcess-1
  5. 必须继承父类的__init__方法,原因在于父类的init还封装着别的参数,必须继承
class MyProcess(Process):  # 必须继承Process,类名可以换

    def run(self):
        # 必须要写成run方法,改了名字默认继承父类,pass,结果就只执行主进程
        print(f"{self.name} is running")
        time.sleep(2)
        print(f"{self.name} is done")  #默认继承父类的init方法

if __name__ == "__main__":
    p = MyProcess()
    p.start()
    print("==主")

# 结果:
# ==主
# MyProcess-1 is running
# MyProcess-1 is done

2.进程的简单应用

1. 串行:所有的任务一个一个的完成(相当于调用三个函数)

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is done")

def task1(name):
    print(f"{name} is running")
    time.sleep(3)
    print(f"{name} is done")

def task2(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is done")

if __name__ == "__main__":
    start_time = time.time()
    task("太白")
    task1("宝元")
    task2("女神")
    print(f"运行时间为:{time.time() - start_time}")

"""
太白 is running
太白 is done
宝元 is running
宝元 is done
女神 is running
女神 is done
运行时间为:6.001795053482056
"""

2. 并发:一个CPU完成多个任务,看起来像是同时完成

并行:多个CPU执行多个任务,真正的同时完成

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(3)
    print(f"{name} is done")

def task1(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is done")

def task2(name):
    print(f"{name} is running")
    time.sleep(5)
    print(f"{name} is done")

if __name__ == "__main__":
    start_time = time.time()
    p = Process(target=task,args=("太白",))  # 创建一个进程对象
    p1 = Process(target=task1,args=("宝元",))  # 创建一个进程对象

    p.start()   #只提示创建就往下走了
    p1.start()  #
    task2("女神") #第一个打印
    print(f"运行时间为:{time.time() - start_time}")#必须等task2执行完

"""
女神 is running
太白 is running
宝元 is running
宝元 is done
太白 is done
女神 is done
运行时间为:5.075502872467041
"""
from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(3)
    print(f"{name} is done")

def task1(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is done")

def task2(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is done")

if __name__ == "__main__":
    start_time = time.time()
    p = Process(target=task,args=("太白",))  # 创建一个进程对象
    p1 = Process(target=task1,args=("宝元",))  # 创建一个进程对象
    p2 = Process(target=task1,args=("女神",))  # 创建一个进程对象

    p.start()
    p1.start()
    p2.start()
    print(f"运行时间为:{time.time() - start_time}")

"""
运行时间为:0.12958216667175293
太白 is running
宝元 is running
女神 is running
宝元 is done
女神 is done
太白 is done
"""

![

3. pid是进程在内存中的唯一标识

在cmd终端输入tasklist查询所有进程的pid
在cmd终端输入tasklist|findstr python查询pycharm中多个进程的pid
在cmd终端输入tasklist|findstr pycharm查询主进程的pid
(在pycharm文件未关闭的前提下才可以找到)

具体操作如下

  1. 如何区分内存中的这些进程?

    • cmd终端获取所有的进程的pid 方法 tasklist
    • 1566291404490
  2. 代码级别如果获取一个进程pid

    • cmd终端获取所有子进程的pid 方法 tasklist|findstr python

    • ![

    • ![

    • import os
      import time
      print(f"子进程:{os.getpid()}")
      time.sleep(50) #关闭了在内存中就看不到了
      
    • cmd终端获取所有主进程的pid 方法 tasklist|findstr pycharm

    • ![

      ![

    import os
    import time
    print(f"主进程:{os.getppid()}")
    time.sleep(50) #关闭了在内存中就看不到了
    
    from multiprocessing import Process
    import os
    
    def task():
        print(f"子进程:{os.getpid()}")   #子进程pid
        print(f"主进程:{os.getppid()}")  #主进程pid
    
    if __name__ == "__main__":
        p = Process(target=task)
        p.start()
        print(f"==主进程{os.getpid()}")  #进程pid
    
    

4. 验证进程之间的空间隔离

1. 主进程为不可变数据类型 : 主不变(空间隔离了,没有关系了)

子进程只是初始数据复制主进程的内容

from multiprocessing import Process
import time
name = "太白"
def task():
    global name
    name = "alexsb"
    print(f"子进程:{name}")

if __name__ == "__main__":
    p = Process(target=task)  
    p.start()  #开辟一个子进程空间,
    print(f"==主:{name}")  #空间隔离,不会变
    time.sleep(2)
    print(f"==主:{name}")  #空间隔离,不会变

2. 主进程为可变数据类型 : 主不变(空间隔离了,没有关系了)

子进程只是初始数据复制主进程的内容

from multiprocessing import Process
import time
lst = ["太白"]
def task():
    lst.append("alexsb")
    print(f"子进程:{lst}")

if __name__ == "__main__":
    p = Process(target=task)
    p.start()  #开辟一个子进程空间,
    print(f"==主:{lst}")  #空间隔离,不会变
    time.sleep(2)
    print(f"==主:{lst}")  #空间隔离,不会变

5. 进程的 join 阻塞 让主进程等待子进程结束之后,在执行主进程

(join后边的主进程内容被阻塞)

1. 一个子进程之间的主进程阻塞

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is gone")

if __name__ == "__main__":
    start_time = time.time()
    p = Process(target=task,args=("太白",)) #创建一个子进程对象
    p.start()
    p.join() #产生阻塞
    print(f"==主:{time.time()-start_time}")  #上边阻塞,要等待子进程执行完毕才执行
  1. 多个子进程之间的主进程阻塞

from multiprocessing import Process
import time

def task(name,sec):
    print(f"{name} is running")
    time.sleep(sec)
    print(f"{name} is gone")

if __name__ == "__main__":
    start_time = time.time()
    p = Process(target=task,args=("太白",2))
    p1 = Process(target=task,args=("宝元",3))
    p2 = Process(target=task,args=("日天",1))

    #以下三个几乎同时进行
    p.start()
    p1.start()
    p2.start()

    #多重阻塞
    p.join()
    print(f"==主1:{time.time() - start_time}")
    p1.join()
    print(f"==主2:{time.time() - start_time}")
    p2.join()
    print(f"==主3:{time.time() - start_time}")
"""
太白 is running
宝元 is running
日天 is running
日天 is gone
太白 is gone
==主1:2.1800968647003174
宝元 is gone
==主2:3.1918866634368896
==主3:3.1918866634368896
"""

3. 优化代码下列代码

from multiprocessing import Process
import time

def task(sec):
    print(f'is running')
    time.sleep(sec)
    print(f' is gone')


if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=(1,))
    p2 = Process(target=task,args=(2,))
    p3 = Process(target=task,args=(3,))

    p1.start()
    p2.start()
    p3.start()

    p1.join()
    p2.join()
    p3.join()
from multiprocessing import Process
import time

def task(sec):
    print(f'is running')
    time.sleep(sec)
    print(f' is gone')

if __name__ == '__main__':
    start_time = time.time()
    lst = []
    for i in range(1,4):
        p = Process(target=task, args=(i,))
        lst.append(p)
        p.start()
    for i in lst:
        i.join()
    print(f"==主:{time.time() - start_time}")

6.进程的其他参数

  1. p.terminate() 杀死子进程(快速的话子进程不会执行)

from multiprocessing import Process
import time

def task(name):
   print(f"{name} is going")
   time.sleep(2)
   print(f"{name} is done")

if __name__ == "__main__":
    p = Process(target=task,args=("太白",))

    p.start()
    #time.sleep(1)
    p.terminate()  #杀死子进程,可以添加睡的时间选择让子进程执行一半时杀死
    print("==主开始")

2. p.is_alive() 判断子进程是否还活着(True,False)

from multiprocessing import Process
import time

def task(name):
   print(f"{name} is going")
   time.sleep(2)
   print(f"{name} is done")

if __name__ == "__main__":
    p = Process(target=task,args=("太白",))

    p.start()
    p.terminate()  #杀死子进程(需要点时间传递)
    # p.join()
    # time.sleep(1)
    print(p.is_alive()) #上方如果不加阻塞代码,时间太短,结果是False
    print("==主开始")

3. p.name() 给实例化对象封装name属性,默认为类名-1

 p = Process(target=task,args=("太白",),name = "alex)

7. 守护进程 子进程守护着主进程,只要主进程结束,子进程跟着就结束

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is done")

if __name__ == "__main__":
    p = Process(target=task,args=("太白",))
    p.daemon = True  #主进程结束,子进程就结束了
    p.start()
    # time.sleep(1)
    # p.daemon = True  # 一定要在子进程开启之前设置
    print("==主")
posted @ 2019-08-20 20:59  lvweihe  阅读(83)  评论(0编辑  收藏  举报