python-----多进程编程

本文介绍Python中进程的创建与管理,包括使用os.fork(), multiprocessing模块的不同方法创建多进程,如实例化Process对象、创建子类及利用进程池。同时探讨了进程间的通信机制,特别是如何使用Queue进行数据传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)进程的创建

编写完毕的代码,在没有运⾏的时候,称之为程序 

正在运⾏着的代码,就成为进程 

注意: 进程,除了包含代码以外,还有需要运⾏的环境等,所以和程序是有区别的

(2)进程的五状态模型

(3)用fock创建子进程

运行代码如下:

import os


print("当前进程的pid:",os.getpid())
print("当前进程的父进程:",os.getppid())

p = os.fork()
if p == 0:
    print("子进程返回的信息")
else:
    print("创建子进程%s,父进程是%d" %(p,os.getppid()))

运行结果如下所示:

使用fock方法的注意事项

1.执⾏到os.fork()时,操作系统会创建⼀个新的进程复制⽗进程的所有信息到⼦进程中 

2.普通的函数调⽤,调⽤⼀次,返回⼀次,但是fork()调⽤⼀次,返回两次 

3.⽗进程和⼦进程都会从fork()函数中得到⼀个返回值,⼦进程返回是0,⽽⽗进程中返回⼦进程的 id号

注意:多进程中,每个进程中所有数据(包括全局变量)都各有拥有⼀份,互 不影响

multiprocessing模块

Windows没有fork调⽤,由于Python是跨平台的, multiprocessing模块就是跨平台版本的多进程模块。multiprocessing模块提供了⼀个Process类来代表⼀个进程对象。 

Process([group [, target [, name [, args [, kwargs]]]]])    

 target:表示这个进程实例所调⽤对象;      

args:表示调⽤对象的位置参数元组; 

kwargs:表示调⽤对象的关键字参数字典;    

name:为当前进程实例的别名;    

 group:⼤多数情况下⽤不到;

Process类常⽤属性:      name:当前进程实例别名,默认Process-N,N为从1开始计数;     pid:当前进程实例的PID值;

多进程编程方法一:实例化对象

运行代码如下:

from multiprocessing import Process
import time
def task1():
    print("正在听音乐")
    time.sleep(1)
def task2():
    print("正在编程......")
    time.sleep(0.5)
def use_multi():
    processes = []
    for i in range(2):
        p = Process(target=task1)
        #让子进程执行任务
        p.start()
        processes.append(p)
    for i in range(5):
        p = Process(target=task2)
        p.start()
        processes.append(p)

    [process.join() for process in processes]
if __name__ == '__main__':
    start_time = time.time()
    use_multi()
    end_time = time.time()
    print(end_time-start_time)

运行结果如下所示:

多进程编程方法2: 创建子类

利用重写run方法

运行代码如下:

from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self,music_name):
        super(MyProcess,self).__init__()
        self.music_name = music_name

    def run(self):
        print("听音乐%s" %(self.music_name))
        time.sleep(1)
if __name__ == '__main__':
    for i in range(10):
        p =MyProcess("音乐%d" %(i))
        p.start()

运行结果如下所示:

多进程编程方法三:利用进程池

为什么需要进程池Pool?

当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。 

Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

进程池Pool其他实现方式

运行代码如下:

import multiprocessing

def job(id):
    print("start %d...." %(id))
    print("end %d...." %(id))
#创建进程池对象
pool = multiprocessing.Pool(processes = 4)
#给进程池分配任务
for i in range(10):
    pool.apply_async(job,args=(i+1,))

pool.close()
#等待所有的子进程执行结束,关闭进程池对象;
pool.join()
print("所有任务执行结束.....")
    

运行结果如下:

课上练习:用多进程判断是否为素数

运行代码如下:

from multiprocessing import Process
def is_prime(num):
    if num == 1:
        return False
    for i in range(2,num):
        if num % i == 0:
            return False
    else:
        return True
def task(num):
    if is_prime(num):
        print("%d是素数" %(num))
def use_mutli():
    ps = []
    for num in range(1,10000):
        p = Process(target=task,args=(num,))
        p.start()
        ps.append(p)
    [p.join() for p in ps]
def no_mutli():
    for num in range(1,10000):
        task(num)
def use_pool():
    from multiprocessing import Pool
    from multiprocessing import cpu_count
    p = Pool(cpu_count())
    p.map(task,list(range(1,10000)))
    p.close()
    p.join()

import time
if __name__ == '__main__':
    start_time = time.time()
    #no_mutli()       #0.5684056282043457
    #use_mutli()
    end_time = time.time()  #7.152557373046875e-07
    use_pool()
    print(end_time-start_time)

运行结果如下:

进程间通信

消息队列

可以使⽤multiprocessing模块的Queue实现多进程之间的数据传递,Queue 本身是⼀个消息列队程序。

Queue.qsize():    返回当前队列包含的消息数量; 

Queue.empty():    如果队列为空,返回True,反之False ; 

Queue.full():    如果队列满了,返回True,反之False; 

Queue.get([block[, timeout]]):     获取队列中的⼀条消息,然后将其从列队中移除,block默认值为True;

Queue.get_nowait():     相当Queue.get(False);

Queue.put(item,[block[, timeout]]):     将item消息写⼊队列,block默认值 为True;

Queue.put_nowait(item):     相当Queue.put(item, False)

进程间通信代码如下:

from multiprocessing import Process
import multiprocessing
import time
class producer(multiprocessing.Process):
    def __init__(self,queue):
        super(producer,self).__init__()
        self.queue = queue
    def run(self):
        for i in range(10):
            self.queue.put(i)
            time.sleep(0.1)
            print("传递消息,内容为%s" %(i))
class Consumer(multiprocessing.Process):
    def __init__(self,queue):
        super(Consumer,self).__init__()
        self.queue = queue
    def run(self):
        while True:
            time.sleep(0.1)
            recvData = self.queue.get()
            print("接受到另一进程传递的数据:%s" %(recvData))

if __name__ == '__main__':
    q = multiprocessing.Queue()
    p1 = producer(q)
    c1 = Consumer(q)
    p1.start()
    c1.start()
    p1.join()
    c1.join()

运行结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值