python进程

  • 时间:
  • 来源:互联网
  • 文章标签:

廿二、进程

进程是正在运行的程序,他是操作系统中,资源分配的最小单位

资源分配:分配的是cup和内存等物理资源

注:进程号是进程的唯一标识;同一个程序执行两次后是两个进程

进程和进程之间是彼此隔离的,通过socket通信

1、并行和并发

并发:一个cpu同一时间不停执行多个程序

并行:多个cpu同一时间不停执行多个程序

2、cpu的进程调度方法

先来先服务fcfs(fist come first server):先来的先执行

短作业优先算法:分配的cpu多,先把短的算完

时间片轮转算法:每一个任务就执行一个时间片的时间,然后就执行其他的

多级反馈队列算法

越是时间长的,cpu分配的资源越少,优先级靠后

越是时间短的,cpu分配的资源越多

3、进程三状态

(1)就绪(Ready)状态

​ 只剩下CPU需要执行外,其它所有资源都已分配完毕称为就绪态

(2)执行(Running)状态

​ cpu开始执行该进程时称为执行状态

(3)阻塞(Blocked)状态

​ 由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程。

​ 例如:等待I/O完成input、申请缓冲区不能满足等等

4、同步 异步/阻塞 非阻塞

场景在多任务中

同步:必须等我这件事干完了,你在干,同一时间只有一条主线,就是同步

异步:没等我这件事情干完,你就在干了,有两条主线,就是异步

阻塞:像input或time.sleep(),就是阻塞,必须要输入一个字符串或等待一段时间,否则代码不往下执行

非阻塞:没有任何等待,正常代码执行

同步阻塞:效率低,cup利用不充分

异步阻塞:比如socketserver,可以同时连接多个,但是彼此都有recv

同步非阻塞:没有类似input或time.slee()的代码,从上到下执行,默认的正常情况代码

异步非阻塞:效率最高,cup过度充分,过度发热

(1) 进程使用的基本语法(无参)

​ process 创建子进程,返回进程的对象p,
​ target指定要执行的任务
​ args指定传递的参数,args的类型是元组,多个参数之间用逗号隔开

# 无参
from multiprocessing import Process
def func():
    print("1.子进程id:{} 2.父进程id:{}".format(os.getpid(), os.getppid()))

if __name__ == "__main__":
    print("3.子进程id:{} 4.父进程id:{}".format(os.getpid(), os.getppid()))
    p = Process(target=func)
    p.start()

(2)创建带有参数的进程

# 有参
def func(n):
    for i in range(1, n+1):
        print("3.子进程id:{},4.父进程id:{}".format(os.getpid(), os.getppid()))

if __name__ == "__main__":
    print("1.子进程id:{},2.父进程:{}".format(os.getpid(), os.getppid()))
    n = 5
    p = Process(target=func, args=(n,))
    p.start()

    for i in range(1, n+1):
        print("*" * i)

(3)进程之间的数据隔离(进程和进程之间是相互独立的)

count = 100
def func():
    global count
    count += 1
    print("我是子进程count={}".format(count))

if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    time.sleep(1)
    print(count)

(4)多个进程可以异步并发,子父进程之间的关系

  • 程序在异步并发任务时,因为cpu调度策略问题,不一定先执行谁或者后执行谁;整体而言,主进程速度快于子进程,cpu遇到阻塞立刻切换其它任务,等到进程的就绪状态在切回来

  • 主程序会默认等待所有的子进程执行结束后,再关闭程序,释放资源;若不等待,子程序并不方便管理,容易造成僵尸进程,在后台不停的占用系统的资源(cpu和内存),不清楚来源

def func(args):
    print("3子进程id:{},4父进程id:{}".format(os.getpid(), os.getppid()), args)

if __name__ == "__main__":
    for i in range(1, 11):
        Process(target=func, args=(i,)).start()
    print("主进程执行结束。。。")

(5)join的使用

​ 必须等待所有的子进程全部执行完毕之后,主进程任务在继续执行(用来同步子父进程的速度)

# (1) join 的基础语法
def func():
    print("发第一封邮件")

if __name__ == "__main__" :
    p = Process(target=func)
    p.start()
    p.join()
    print("发第二封邮件")
    
# (2) 多个子进程配合join使用
def func(index):
    print("发送第%s封邮件" % (index))

if __name__ == "__main__":
    lst = []
    for i in range(10):
        p = Process(target=func, args=(i,))
        p.start()
        lst.append(p)
    for i in lst:
        print(i)
        i.join()
    print("主进程最后一封邮件")

(6)使用自定义方式创建进程

​ 自定义类创建进程要求:

  • 必须继承Process这个父类

  • 所有进程执行任务的逻辑要写run方法里面

# (1) 基本语法
class MyProcess(Process):
    def run(self):
        print('1子进程id:{},2父进程id:{}'.format(os.getpid(), os.getppid()))

if __name__ == "__main__":
    p = MyProcess()
    p.start()
    print("3子进程id:{},4父进程id:{}".format(os.getpid(), os.getppid()))
    
# (2) 有参数的进程函数
class MyProcess(Process):
    def __init__(self, arg):
        # 手动调用一下父类的构造方法(实现进程的创建)
        super().__init__()
        self.arg = arg
    def run(self):
        print("1子进程id:{},2父进程id:{}".format(os.getpid(), os.getppid()))

if __name__ == "__main__":
    p = MyProcess("我是参数")
    p.start()
    print('3子进程id:{},4父进程id:{}'.format(os.getpid(), os.getppid()))

5、守护进程

可以给子进程贴上守护进程的名字,该进程会随着主进程代码执行完毕而结束(为主进程守护)

(1)守护进程会在主进程代码执行结束后终止

(2)守护进程内无法在开启子进程,否则抛出异常

守护进程守护的是主进程

通过进程对象.daemon = True 设置当前进程为守护进程

注:必须写在start()调用之前

默认情况下,主进程会等待所有子进程执行完毕后,关闭程序释放资源

守护进程在主进程代码执行结束后,直接杀掉

from multiprocessing import Process
# (1)基本用法
def func():
    print("start 当前子进程")
    print("end   当前子进程")

if __name__ == "__main__":
    p = Process(target=func)
    p.daemon = True
    p.start()
    print("主进程执行结束 ... ")

# (2)多个子进程的场景
import time
def func1():
    count = 1
    while True:
        print("*" * count)
        time.sleep(0.5)
        count += 1
    
def func2():
    print("start func2当前子进程")
    time.sleep(2)
    print("end   func2当前子进程")
    

if __name__ == "__main__":
    p1 = Process(target=func1)
    p2 = Process(target=func2)
    
    # 设置当前进程为守护进程
    p1.daemon = True
    
    p1.start()
    p2.start()
    
    time.sleep(1)
    
    # 非守护进程,主进程还是会默认等待的.
    print("主程序代码结束....")

# (3)守护进程的实际用途:监控报活
import time
# 监控报活
def alive():
    while True:
        print("给监控服务器发消息, 当前5号服务器功能正常 i am ok ~")
        time.sleep(1)

# 当前服务器正常完成的功能
def func():
    # while True:
    time.sleep(5)
    print("当前5号服务器功能,统计财务报表~")


if __name__ == "__main__":
    p1 = Process(target=func)
    p2 = Process(target=alive)
    p2.daemon = True
    
    p1.start()
    p2.start()
    
    # 等待p1子进程执行结束之后,下面的主程序的代码才会放行;
    p1.join()
    
    print("当前服务器状态:统计财务报表功能异常.....")

本文链接http://www.taodudu.cc/news/show-83180.html