欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多进程编程

程序员文章站 2022-06-19 13:26:27
...

多进程编程

概念

程序: 计算机中存储的二进制代码

进程: 计算机中运行的程序

多进程: 多个进程同时运行

进程的创建

Linux环境下执行

实例:

import os
import time
def sing():
    for v in range(3):
        print("我在唱歌")
        time.sleep(1)
def dance():
    for v in range(3):
        print("我在跳舞")
        time.sleep(1.1)
time_start = time.time()
# 创建多个进程
pid = os.fork()
# print(f'子进程{os.getpid()},父进程{os.getppid()}')
if pid == 0:
    # 子进程执行
    sing()
else:
    # 父进程执行
    dance()
time_end = time.time()
# 如何父进程先结束,子进程就不再执行
print(f"耗费{time_end-time_start}")

getpid() 获取当前进程的id,getppid()获取父进程的id

子进程的id永远为0,父进程的id永远大于0

os.fork() 是创建多个进程

多进程修改全局变量

import os
num = 0
pid = os.fork()
if pid == 0:
    num += 1
    print("当前{}".format(num))
else:
    num += 1
    print("当前{}".format(num))
# 结果都为1

创建多进程后,子进程会复制父进程的内存空间,进程执行时是修改的自己的内存空间,输出的也是自己内存中的值

多次fork

import os
pid = os.fork()
if pid == 0:
    print("hello")
else:
    print("hello")
pid = os.fork()
if pid == 0:
    print("hello")
else:
    print("hello")
# 执行6次

python多进程编程

实例:

from multiprocessing import Process
import os
import time
def sing(num, name):
    print(f"当前pid:{os.getpid()}")
    for v in range(num):
        print(f"{name}在唱歌")
        time.sleep(1)
def dance(num, name):
    print(f"当前pid:{os.getpid()}")
    for v in range(num):
        print(f"{name}在跳舞")
        time.sleep(1.1)
def main():
    time_start = time.time()
    # 创建一个子进程实例
    pro1 = Process(target=sing, args=(3,), kwargs={"name": "libai"})
    # 开始一个子进程
    print(pro1.is_alive())    # False
    pro1.start()
    # 进程是否还在执行
    print(pro1.is_alive())     # True
    pro2 = Process(target=dance, args=(3,), kwargs={"name": "dufu"})
    pro2.start()
    # 等待pro1结束后在执行后面代码
    pro1.join()
    # 等待pro2结束后在执行后面代码
    pro2.join()
    print(pro1.is_alive())   # False
    print(f"当前pid:{os.getpid()},耗费{time.time()-time_start}")
if __name__ == '__main__':
    main()

Process常用参数和方法

​ target:表示这个进程实例所调用对象

​ args:表示调用对象的位置参数元组

​ kwargs:表示调用对象的关键字参数字典

​ start():启动进程实例(创建子进程)

​ is_alive():判断进程实例是否还在执行

​ join([timeout]):是否等待进程实例执行结束,或等待多少秒

继承类Process

from multiprocessing import Process
class Proce(Process):
    def __init__(self, name):
        # 在初始化时要调用一下父类的初始方法
        #因为Process类本身也有__init__方法,这个子类相当于重写了这个方法,
    	#但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性,
    	#最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作
        # Process.__init__()
        super(Proce, self).__init__()
        self.name = name
    def run(self):
        print(f"进程:{self.name}")
def main():
    p1 = Proce("子进程")
    # 调用start方法时会自动调用run方法
    p1.start()
    p1.join()
    print('父进程')
if __name__ == '__main__':
    main()

进程池

import os
from multiprocessing import Pool
def job(args):
    print("当前进程{},{}".format(os.getpid(), args))
    time.sleep(random.random() * 3)
# 定义进程池
pool = Pool(4)
for v in range(10):
    # 调用方法
    pool.apply_async(job, (v,))
# 关闭进程池
pool.close()
# 等待进程结束
pool.join()

进程间的通信

queue的使用

Queue.qsize():	返回当前队列包含的消息数量;
Queue.empty():	如果队列为空,返回True,反之False ;
Queue.full():	如果队列满了,返回True,反之False;
Queue.put():   存储值
Queue.get():   取值

实例:

from multiprocessing import Process, Queue
def write(queue):
    # 将数据写入队列
    for v in ["a", "b", "c", "d"]:
        queue.put(v)
def read(queue):
    # 获取队列里的值
    while True:
        if not queue.empty():
            print(queue.get())
        else:
            break
def main():
    # 创建一个队列
    queue = Queue()
    p = Process(target=write, args=(queue,))
    p.start()
    p.join()
    p2 = Process(target=read, args=(queue,))
    p2.start()
    p2.join()
    print("结束任务")
if __name__ == '__main__':
    main()

进程扩展

孤儿进程:父进程结束了,子进程还没结束

僵尸进程:子进程结束了,而父进程不能收回子进程的内存空间

​ 查看僵尸进程: ps -ef |grep “def”

守护进程:父进程结束了,子进程还没结束,子进程被1号进程接收,不能够直接退出子进程

转载于:https://my.oschina.net/u/4161332/blog/3072248