python-- 启动进程的两种方式
进程
进程:
是指正在执行的程序。是程序执行过程中的一次 指令,数据集等的集合。也可以叫做程序的一次执行过程。进程是一个动态的概念。
进程由三大部分组成:代码段,数据段,PCB:进程管理控制
因为有GIL锁的存在,在Cpython中,没有真正的线程并行。但是有真正的多进程并行当你的任务是计算密集的情况下,使用多进程好
总结:在CPython中,IO密集用多线程,计算密集用多进程
进程的三大基本状态:
- 就绪状态:已经获得运行需要的所有资源,除了CPU
- 执行状态:已经获得了所有资源包括cpu,处于正在运行
- 阻塞状态:因为各种原因,进程放弃了cpu,导致进程无法继续执行,此时进程处于内存中,继续等待获取cpu
进程的一个特殊状态:
- 挂起状态:是指因为种原因,进程放弃了cpu,导致进程无法继续执行,此时进程被踢出内存。
并行 : 两个进程在同一时间点发生
并发 : 两个进程在同一时间间隔内运行
同步 : 某一个任务的执行必须依赖于另一个任务的返回结果
异步 : 某一个任务的执行,不需要依赖于另一个任务的返回,只需要告诉另一个任务一声
阻塞 : 程序因为类似于IO等待、等待事件等导致无法继续执行。
非阻塞:程序遇到类似于IO操作时,不再阻塞等待,如果没有及时的处理IO,就报错或者跳过等其他操作
启动进程的两种方式
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
- 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。
- 进程在执行的过程中如果阻塞,例如等待输入input,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。
第一种方式
import os import time from multiprocessing import Process def func(n): time.sleep(5) print('这里是子进程,子进程的pid是%s,父进程的pid是%s' % (os.getpid(), os.getppid())) if __name__ == '__main__': p = Process(target=func, args=(1,)) # 实例化一个进程对象 p.start() # 开启一个子进程 print('这里是父进程,父进程的pid是%s,父父的pid是%s' % (os.getpid(), os.getppid()))
结果
这里是父进程,父进程的pid是3620,父父的pid是2762
这里是子进程,子进程的pid是3621,父进程的pid是3620
os.getpid()获取的是当前进程自己的pid
os.getppid()获取的是当前进程的父进程的pid
第二种方式,继承的方式
from multiprocessing import Process class MyProcess(Process): def __init__(self): super(MyProcess, self).__init__() def run(self): print('这是以继承类的方式开启的子进程') if __name__ == '__main__': p1 = MyProcess() p1.start() # 是指,解释器告诉操作系统,去帮我开启一个进程,就绪状态,方法必须为run # p1.run()# 告诉操作系统,现在马上帮我执行这个子进程 执行
结果:
这是以继承类的方式开启的子进程
import multiprocessing, time def run(n): time.sleep(2) print('%s in the run...' % n) if __name__ == '__main__': for i in range(5): m = multiprocessing.Process(target=run,args=(i,)) m.start()
结果
0 in the run... 1 in the run... 2 in the run... 3 in the run... 4 in the run...
2秒后一起执行的