python进程池如何重复利用_Python多进程、进程池和内存碎片消息队列,记忆,之,python...

本文详细介绍了Python中的多进程操作,包括Process的使用、进程间通信以及进程池Pool的应用。通过实例展示了如何创建、管理和同步进程,以及如何使用Queue进行进程间的通信。此外,还讲解了在Windows上生成可执行文件时防止资源溢出的方法。最后,通过具体的代码示例演示了如何在进程池中使用Queue实现消息传递。
摘要由CSDN通过智能技术生成

# 多进程

import os

from multiprocessing import Process, current_process

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

# group分组,实际上不怎么使用

# target表示调用对象,传入任务执行函数做为参数,注意是函数名,不带括号

# args表示给调用对象以元组的形式提供 参数,两个参数时args=(m,n),一个参数时args=(m,),注意元组逗号

# kwargs表示调用对象的字典的传参

# name 是别名,相当于给这个进程取一个名字,在进程数量较多时,这个参数比较好用

# 关于进程方法的操作

# start()让进程执行target调用的对象

# join()阻塞,默认情况下,主进程不会等到子进程任务结束后主进程才结束,使用join()可以让主进程等待子进程任务结束后再结束

# terminate()结束当前,无论任务是否完成

# multiprocessing.freeze_support() 在windows上生成GUI等可执行文件时(.exe文件)时,

# 可能会无限开启新窗口或者新进程导致CPU或内存溢出,可以使用该命令解决,

# os.getpid()获取子进程id

# os.getppid()获取父进程id

# is_alive() 返回布尔值,Ture时进程开启

def test(i):

print(f"----------------子进程{os.getpid()}---------父进程{os.getppid()}---", current_process().name)

# ----------------子进程7720---------父进程10572--- 当前任务1

# ----------------子进程11556---------父进程10572--- 当前任务2

# ----------------子进程8756---------父进程10572--- 当前任务3

# ----------------子进程9400---------父进程10572--- 当前任务4

# ----------------子进程8408---------父进程10572--- 当前任务5

# if __name__ == '__main__':

# for i in range(1, 6):

# p = Process(target=test, args=(i,), name="当前任务{}".format(i))

# p.start()

# p.join() # 由于阻塞,速度会降低,但是在进程通讯方面这个方法可以使用

# 进程池

from multiprocessing import Pool, Manager

import time, random

# 部分参数

# pool.apply_async() 异步非阻塞

# pool.apply() 阻塞

# pool.join() 主进程创建或添加任务之后,默认主进程不等待子进程任务结束后再结束,

# 如果主进程任务完成后立马结束,若没有使用join()就会导致进程池中的任务不执行

def worker(msg):

start_time = time.perf_counter()

print(f"{msg}开始执行,当前的子进程是{os.getpid()}")

time.sleep(random.random() * 2)

stop_time = time.perf_counter()

print(msg, f"执行完毕,耗时{(stop_time - start_time).__round__(2)}")

def main():

pool = Pool(3) # 定义一个进程池,最大进程数为3

for i in range(0, 11):

# 每次循环将会用空闲出来的子进程调用目标

pool.apply_async(func=worker, args=(i,))

print("开始")

pool.close() # 关闭进程池,关闭后pool不再接受新的请求

pool.join() # 等待pool所有的子进程执行完成,必须放在close语句之后

print("结束")

# if __name__ == '__main__':

# main()

# 进程之间的通信

# Queue的使用

from multiprocessing import Queue, cpu_count

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

# Queue.empty() 如果队列为空,返回True,条件判断

# Queue.full() 判断队列是否满来,满了返回True

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

# Queue.get_nowait() 相当于Queue.get(False)

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

# Queue.put_nowait() 相当于Queue.put(item,Flase)

# 使用方法

# q = Queue(num) num可以为空或者num为负数时代表可接受的消息无上限

# 关键参数block,如果block使用默认值,且没有设置timeout(单位秒),,如果消息队列空了,则程序被阻塞(停在读取状态),

# 直到从消息队列读到消息位置,如果设置来timeout参数,则会等待timeout秒,若还是没有读取到消息,则抛出Queue.Empty异常;

# 如果block值为False,消息队列如果为空,就会立抛出Queue.Empty异常

# q = Queue(3) # 初始化一个Queue对象,最多可以接收三条put消息

# q.put("消息1")

# q.put("消息2")

# print(q.full())

# q.put("消息3")

# print(q.full())

# try:

# q.put("消息4", block=True, timeout=5)

# except Exception as e:

# print(f"消息队列已满,5秒后报错,现在消息队列的数量是{q.qsize()}", e)

# try:

# q.put_nowait("消息4")

# except Exception as e:

# print(f"消息队列已满,直接报错,现在消息队列的数量是{q.qsize()}", e)

# 先判读消息队列是否已满,然后再写入数据

# if not q.full():

# q.put_nowait("消息4")

# 读取消息时,先判读消息队列是否为空,再读取消息

# if not q.empty():

# for i in range(q.qsize()):

# print(f"循环读取消息队列数据{q.get_nowait()}")

# 两个进程之间的通信

# 写入队列消息

def write(q):

for value in ["A", "B", "C"]:

print(f"put {value} to queue")

q.put(value)

time.sleep(random.random())

# 读取队列消息

def read(q):

while True:

if not q.empty():

value = q.get(True)

print(f"get {value} from queue")

time.sleep(random.random())

else:

break

# if __name__ == '__main__':

# # 父进程创建Queue,并把实例q传给各个子进程

# q = Queue()

# pw = Process(target=write, args=(q,))

# pr = Process(target=read, args=(q,))

# # 启动子进程pw,写入消息

# pw.start()

# # 等待pw结束

# pw.join()

# # 启动子进程pr,读取消息

# pr.start()

# pr.join()

# print("所有消息都已经读写成功")

# 在进程池中使用Queue

# Pool创建的进程池,需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否则报错:

# RuntimeError: Queue objects should only be shared between processes through inheritance.

# 错误翻译>>>运行时错误:队列对象只能通过继承在进程之间共享。

def reader(q):

print(f"reader启动{os.getpid()},父进程为{os.getppid()}")

for i in range(q.qsize()):

print(f"reader从Queue获取到消息:{q.get(True)}")

def writer(q):

print(f"writer{os.getpid()},父进程为{os.getppid()}")

for i in "laotie":

q.put(i)

print(f"writer向Queue写入来消息:{i}")

if __name__ == '__main__':

print(f"{os.getpid()} start")

q = Manager().Queue()

pool = Pool(cpu_count())

# print(f"当前cpu的信息为{cpu_count()}", type(cpu_count())) # 当前cpu的信息为4

# 使用阻塞模式创建进程,这样就不需要在reader中使用死循环,就可以让writer执行完在执行reader

pool.apply(func=writer, args=(q,))

pool.apply(func=reader, args=(q,))

# 当进程池close的时候并未关闭进程池,只是会把状态改为不可再插入元素的状态

pool.close()

pool.join()

print(f"{os.getpid()} end")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值