进程之间的通信
在python中,当两个进程需要同时工作,相互通信,这时候使用队列可以实现。
python中的队列通过从 multiprocessing中导入 Queue,它是专门在进程中使用的队列
from multiprocessing import Queue
q = Queue(2)
q.put(1)
q.put("D")
print(q.get())
print(q.get())
print(q.empty())
通过put来传入数据,通过get取出。取出完毕可以通过empty进行判断,取出完毕返回True
python中的创建进程需要导入multiprocessing.Process
让我们创建两个进程来测试一下
import multiprocessing
man_data =[]
def download(q):
lis = [1,2,3]
for i in lis:
q.put(i)
print("添加完毕")
def manage_data(q):
while True:
man_data.append(q.get())
if q.empty():
break
print(man_data)
def main():
# 默认的容量根据内存来定义
q = multiprocessing.Queue()
p1 = multiprocessing.Process(target=download, args=(q,))
p2 = multiprocessing.Process(target=manage_data, args=(q,))
p1.start()
p2.start()
if __name__ == '__main__':
main()
进程池之间的通信
如果需要多个进程,一个一个创建过于麻烦,通过multiprocessing.Poor
来创建进程池,初始化Poor时,可以指定最大的进程个数,当进程池没有满,就会创建新的进程来执行该请求,如果进程池满了,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
进程池运行的时候,程序是堵塞状态。所以需要用close来关闭进程池,不再接收新的请求
- apply_async():添加进程任务
- close():关闭进程池,不再接收新的请求
- join():优先执行子进程中的任务,主进程最后执行,要在close()的后面
如果在关闭进程池的情况下添加进程任务,会报错
先简单看一下进程池的创建:
import os, time
from multiprocessing import Pool
def worker(msg):
t_start = time.time()
print(f"{msg}开始执行,进程号为{os.getpid()}")
#pid 子进程号 ppid父进程号
time.sleep(2)
t_stop = time.time()
print(msg,f"执行完成,耗时{t_stop-t_start}")
if __name__ == '__main__':
# 创建进程池
po = Pool(2)
for i in range(10):
po.apply_async(worker, (i,))
print(123)
#关闭进程池,不再接收新的请求
po.close()
po.join()
进程池之间的通信,通过导入multiprocessing.Manager().Queue()
import multiprocessing
import sys
import traceback
## 进程池通信,使用进程池队列通信
def demo1(q):
# 进程池里面的程序,如果出现异常,不会主动抛出,而是会阻塞
try:
for i in(1,5):
q.put(i)
except Exception as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_tb(exc_traceback_obj)# 标记出错的位置
def demo2(q):
print(q.get())
if __name__ == '__main__':
q = multiprocessing.Manager().Queue()
po = multiprocessing.Pool()
po.apply_async(demo1, args=(q,))
po.apply_async(demo2, args=(q,))
po.close()
po.join()
实现多任务文件夹复制
需求1:实现多任务文件夹复制
• 获取用户要复制的文件夹名字
• 创建一个新的文件夹
• 获取文件夹所有待拷贝的文件名字
• 创建进程池
• 添加拷贝任务
需求2:实现进度条
import multiprocessing
import os
def copy_file(file_name,new_fold_name,old_fold_name):
# 读取文件内容 再保存到新的文件夹中
with open(old_fold_name + "/" +file_name, "rb") as f:
content = f.read()
with open(new_fold_name + "/"+ file_name, "wb") as n_f:
n_f.write(content)
def main():
# 获取用户要复制的文件夹名称
old_fold_name = input("请输入要复制的文件夹名字:")
#创建新的文件
new_fold_name = old_fold_name+"附件"
if not os._exists(new_fold_name):
os.makedirs(new_fold_name)
# 获取老文件夹下,所有需要被拷贝文件的名字
file_names = os.listdir(old_fold_name)
# 同步 拷贝创建进程池
po = multiprocessing.Pool()
for file_name in file_names:
print(file_name)
po.apply_async(copy_file, args=(file_name,new_fold_name,old_fold_name))
po.close()
# 文件总数
file_count = len(file_names)
copy_file_num = 0
while True:
copy_file_num+=1
print("拷贝进度%2.f%%"%(copy_file_num *100/file_count))
if copy_file_num >= file_count:
break
po.join()
if __name__ == '__main__':
main()