python进程|线程|协程

Posted wangzihong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python进程|线程|协程相关的知识,希望对你有一定的参考价值。

进程(Process)

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

  (1)资源分配:分配的是cpu和内存等物理资源

  (2)进程号是进程的唯一标识

  2)同一个程序执行两次之后是两个进程

  3)进程和进程之间的关系: 数据彼此隔离,通过socket通信

获取进程id

import os
res = os.getpid() # 获取当前进行id (当前子进程)
print(res)
res = os.getppid() # 获取父进程id
print(res)

# result 
"""
13724
13800
"""

进程的基本用法

from multiprocessing import Process
import time
import os
def func():
    print("S2>>>当前子进程id:%s,它的父进程id:%s" %(os.getpid(),os.getppid()))

if __name__ == "__main__":
    print("S1>>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    p = Process(target=func) # 创建子进程 target = 函数 单独用一个进程去执行谁,去完成哪个任务
    p.start() # 调用子进程

# result
"""
S1>>>子进程id:7576,父进程id:13800
S2>>>当前子进程id:7100,它的父进程id:7576
"""

带有参数的函数

  异步程序:不等没一行代码执行完毕,就往下执行其它代码

from multiprocessing import Process
import time
import os
def func():
    for i in range(1,5):
        print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))

if __name__ == "__main__":
    print("S1>>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    p = Process(target=func)
    p.start()

    n = 5
    for i in range(1,n+1):
        print("*" * i )
        
# result 
"""
S1>>>子进程id:7928,父进程id:13800
*
**
***
****
*****
S2>>>当前子进程id:8112,它的父进程id:7928
S2>>>当前子进程id:8112,它的父进程id:7928
S2>>>当前子进程id:8112,它的父进程id:7928
S2>>>当前子进程id:8112,它的父进程id:7928
"""

进程之间数据,彼此隔离

from multiprocessing import Process
import time
import os
count = 99
def func():
    global count
    count += 1
    print("当前子进程id:%s"%(os.getpid()),count)

if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    time.sleep(1) # 让子进程跑完,看是否通过子进程修改
    print("主进程",count)

# result 
"""
当前子进程id:1956 100
主进程 99
"""

多进程之间的并发

  多程序并发时,因为cpu的调度策略,任务的执行是互相抢占cpu资源的过程

from multiprocessing import Process
import time
import os
def func(args):
    print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))
    print("end>>>",args)

if __name__ == "__main__":
    for i in range(10):
        Process(target=func,args=(i,)).start()
    print("主进程执行结束...")
    
# result 
"""
主进程执行结束...
S2>>>当前子进程id:10376,它的父进程id:9932
end>>> 2
S2>>>当前子进程id:13476,它的父进程id:9932
end>>> 1
S2>>>当前子进程id:11812,它的父进程id:9932
end>>> 3
S2>>>当前子进程id:13936,它的父进程id:9932
end>>> 4
S2>>>当前子进程id:2384,它的父进程id:9932
end>>> 7
S2>>>当前子进程id:7024,它的父进程id:9932
end>>> 5
S2>>>当前子进程id:14284,它的父进程id:9932
end>>> 8
S2>>>当前子进程id:4816,它的父进程id:9932
end>>> 9
S2>>>当前子进程id:120,它的父进程id:9932
end>>> 6
S2>>>当前子进程id:8604,它的父进程id:9932
end>>> 0
"""

主进程和子进程之间的关系

(1)主进程执行完所有代码,等待子进程全部结束,再终止程序

(2)不等待,子进程变成僵尸用户,在后台不停运行,耗费资源

from multiprocessing import Process
import time
import os
def func(args):
    print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))
    time.sleep(0.1)
    print("end>>>",args)

if __name__ == "__main__":
    for i in range(10):
        Process(target=func,args=(i,)).start()
    print("主进程执行结束...")
    
# result 
"""
主进程执行结束...
S2>>>当前子进程id:10092,它的父进程id:6304
S2>>>当前子进程id:11220,它的父进程id:6304
S2>>>当前子进程id:12992,它的父进程id:6304
S2>>>当前子进程id:8384,它的父进程id:6304
S2>>>当前子进程id:3824,它的父进程id:6304
S2>>>当前子进程id:12880,它的父进程id:6304
S2>>>当前子进程id:6352,它的父进程id:6304
end>>> 0
end>>> 2
S2>>>当前子进程id:7160,它的父进程id:6304
end>>> 9
end>>> 7
S2>>>当前子进程id:6676,它的父进程id:6304
end>>> 5
end>>> 8
end>>> 3
S2>>>当前子进程id:7488,它的父进程id:6304
end>>> 1
end>>> 6
end>>> 4
"""

join

  等待子进程执行完毕之后,主进程再向下执行

基本用法

from multiprocessing import Process
import time
import os
def func():
    print("发送第一封邮件")

if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    time.sleep(1)
    p.join() # 针对于p进程对象来说,必须等待p这个进程任务执行完毕之后,主进程的代码在向下执行
    print("发送第二封邮件")
    
# result 
"""
发送第一封邮件
发送第二封邮件
"""

多个子进程

  多个子进程通过join加阻塞,可以实现同步控制

from multiprocessing import Process
import time
import os
def func(index):
    print("第%s封邮件发送..."%(index))

if __name__ == "__main__":
    lst = [] # 初始化一个列表
    for i in range(5):
        p = Process(target=func,args=(i,))
        p.start()
        lst.append(p)
        p.join()

    # 循环列表中每一个进程,都加上join,保证每个子进程执行完毕,保证同步性
    for i in lst:
        i.join()
    print("发送最后一封邮件...")
    
# result 
"""
第0封邮件发送...
第1封邮件发送...
第2封邮件发送...
第3封邮件发送...
第4封邮件发送...
发送最后一封邮件...
"""

自定义类方式创建进程

基本用法

from multiprocessing import Process
import time
import os
class MyProcess(Process): # 必须继承父类Process
    def run(self): # 必须写成run方法
        print(">>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))

if __name__ == "__main__":
    p = MyProcess()
    p.start()
    print(">>>主进程id:%s"%(os.getpid()))
    
# result 
"""
>>>主进程id:9988
>>>子进程id:14248,父进程id:9988
"""

带参数子进程函数

from multiprocessing import Process
import time
import os
class MyProcee(Process):
    def __init__(self,arg):
        super().__init__() # 必须调用一下父类的构造方法
        self.arg = arg
    def run(self):
        print(">>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
        print(self.arg)

if __name__ == "__main__":
    lst = []
    for i in range(10):
        p = MyProcee("参数:%s"%(i))
        p.start()
        lst.append(p)

    for i in lst:
        i.join()
    print("最后打印子进程id",os.getppid())
    
# result 
"""
>>>子进程id:7488,父进程id:8596
参数:6
>>>子进程id:11300,父进程id:8596
参数:8
>>>子进程id:12048,父进程id:8596
参数:4
>>>子进程id:7868,父进程id:8596
参数:0
>>>子进程id:4792,父进程id:8596
参数:5
>>>子进程id:10764,父进程id:8596
参数:2
>>>子进程id:10852,父进程id:8596
参数:1
>>>子进程id:9348,父进程id:8596
参数:3
>>>子进程id:9860,父进程id:8596
参数:7
>>>子进程id:8956,父进程id:8596
参数:9
最后打印子进程id 13800
"""

并行和并发

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

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

cpu的进程调度方法

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

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

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

(4)多级反馈队列算法

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

进程三状态图

技术图片

(1)就绪(Ready)状态-->只剩下CPU需要执行外,其他所有资源都已分配完毕 称为就绪状态。

(2)执行(Running)状态 --> cpu开始执行该进程时称为执行状态

(3)阻塞(Blocked)状态 --> 由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成input、申请缓冲区不能满足等

同步|异步/阻塞|非阻塞

场景在多任务中

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

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

  阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行

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

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

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

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

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

守护进程

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

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

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

 基本用法

from multiprocessing import Process
import time
import os
def func():
    print("子进程start...")
    time.sleep(0.1)
    print("子进程end...")

if __name__ == "__main__":
    p = Process(target=func)
    p.daemon = True # 在start开始前设置该进程为守护进程
    p.start()
    print("主进程执行结束...")
    
# result 
"""
主进程执行结束...
"""

 多个子进程

  (1)当主进程里面的代码全部执行完毕,守护进程自动终止

  (2)func1是守护进程,func2是非守护进程

from multiprocessing import Process
import time
import os
def func1():
    count = 1
    while True:
        print("*" * count)
        time.sleep(0.5)
        count += 1

def func2():
    print("func2 start...")
    time.sleep(2)
    print("func2 end...")

if __name__ == "__main__":
    p1 = Process(target=func1)
    p1.daemon = True
    p2 = Process(target=func2)
    p1.start()
    p2.start()

    time.sleep(1)
    print("主进程代码执行完毕...")

# result
"""
func2 start...
*
**
主进程代码执行完毕...
func2 end...
"""

 守护进程应用--报活

from multiprocessing import Process
import time
import os
def alive():
    while True:
        print("一号服务主机ok...")
        time.sleep(1) # 相隔1秒报活

def func():
    print("一号服务主机负责统计日志信息")
    time.sleep(3)

if __name__ == "__main__":
    p1 = Process(target=alive)
    p1.daemon = True
    p1.start()
    p2 = Process(target=func)
    p2.start()
    p2.join() # join添加阻塞,join执行结束,代表服务统计功能失败
    print(" ... ")

# result
"""
一号服务主机ok...
一号服务主机负责统计日志信息
一号服务主机ok...
一号服务主机ok...
一号服务主机ok...
 ... 
"""

 

以上是关于python进程|线程|协程的主要内容,如果未能解决你的问题,请参考以下文章

Python之进程线程协程篇

Python之路(十八):进程,线程,协程

python——进程线程协程

python 多进程,多线程,协程

python进程线程协程

python的进程/线程/协程