通过同时运行多个程序来利用闲置的运算能力,通过将CPU的注意力分散在一系列的任务上,可使其运算能力不至于浪费在其中任何一个等待外部事件触发的任务上
★ 很多的任务看起来像同时执行,在时间上重叠且并行,这种技巧通常称为 并行处理
-
-
二者均依赖于操作系统的底层服务来执行Python代码
-
二者在接口,跨平台移植性和通信方面有很大差异
-
Windows下的Python标准版本不支持进程分支
-
分支的进程是构建并行任务的传统做法,也是Unix工具集的基本组成部分
★ 分支是基于复制的
-
当程序调用分支例行程序时,操作系统会创建该程序及其在内存中的进程的副本,然后开始与原有的程序并行的运行该副本
-
有些系统并不是真正的复制原有程序,但新的副本会像真实副本一样运行
分支操作后
-
原有的进程副本被称为 父进程
-
由
os.fork
创建的副本被称为 子进程 -
父进程可以分出任意数量的子进程,而子进程可以再分出子进程
所有的分支进程在操作系统的控制下独立地并行运行,并且子进程在父进程结束后还可以继续运行
启动新的进程 os.fork
-
为调用函数创建了一个副本,为每个副本返回不同的值
-
在子进程中返回0
-
在父进程中返回新的子进程ID
-
为了在子进程中创建不同的进程,一般会对返回的结果进行检验,如下面的例子,仅仅在子进程中运行child函数
"""分支出子进程,知道你输入q""" import os def child(): while True: print("Hello from child", "进程ID:", os.getpid(), "父进程ID:", os.getpgid(os.getpid())) os._exit(0) # 子进程返回到父进程中,分支自己的子进程,但是父进程拥有子进程的子进程,比较重要 def parent(): while True: newpid = os.fork() # 创建一个子进程 print("创建子进程---》", newpid) if newpid == 0: child() else: print("Hello from Parent", "进程ID:", os.getpid(), "父进程ID:", os.getpgid(os.getpid())) if input() == 'q': break parent()
分支进程得到原有进程的全局内存中内容的副本,
- 包括所有打开的文件描述符(标准输入和输出),文件等全局对象在子进程开始时拥有相同的值
- 但是全局内存是被复制了而非共享,如果某个子进程改变了某个全局对象,也只是修改了自己的副本
分支通常是启动独立运行的程序的基础
-
子进程不在同一个文件中调用函数
-
而是运行一个全新的程序
-
os.exec
用一个全新的程序代替(执行覆盖)当前进程中正在运行的程序 -
os.fork
和os.execlp
组合意味着开始一个新的进程,并在其中运行一个新的程序 -
启动与原有程序并行运行的新程序
-
1 import os 2 3 parm = 0 4 5 while True: 6 parm += 1 7 pid = os.fork() 8 if pid == 0: 9 os.execlp('python', 'python', 'child.py', str(parm)) 10 assert False, 'error starting program' 11 else: 12 print("Child is", pid) 13 if input() == 'q': break 14 15 ## child.py 16 import os, sys 17 print("Hello from child", os.getpid(), sys.argv[1])