进程的知识复习。
进程之间的通信
进程池
进程池之间的通信
多任务⽂件夹复制
进程间不共享全局变量
import threading
import multiprocessing
import time
"""
进程之间不共享全局变量
"""
num = 100
def demo1():
global num
num += 1
print(f"demo1:{num}")
def demo2():
print(f"demo2:{num}")
def main():
# t1 = threading.Thread(target=demo1)
# t2 = threading.Thread(target=demo2)
#
# t1.start()
# t2.start()
p1 = multiprocessing.Process(target=demo1)
p2 = multiprocessing.Process(target=demo2)
p1.start()
p2.start()
if __name__ == '__main__':
main()
进程队列
"""
队列:先进先出 (排队买奶茶)
栈:先进后出 (洗碗)
"""
"""
普通队列
"""
# from queue import Queue
#
# # 创建队列 3
# q = Queue(3)
#
# # 2.存数据
# q.put(1)
# q.put("D")
# q.put(["ly","lh","mt"])
#
# # 判断是否存满
# # print(q.full())
#
# # 存满再存 阻塞
# # q.put({"name":"amy"})
#
# # 不阻塞 ,直接报错
# # q.put_nowait({"name":"amy"}) # queue.Full
#
#
# # 3.移出元素
# print(q.get())
# print(q.get())
# print(q.get())
#
# # 判断是否移空
# print(q.empty())
#
# # 超出 阻塞
# # print(q.get())
# # 超出 报错
# print(q.get_nowait()) # queue.Empty
"""
进程的队列
"""
# from multiprocessing import Queue
import multiprocessing
q = multiprocessing.Queue(2)
q.put("hello")
q.put("world")
print(q.get())
print(q.get())
使用进程的队列实现进程间通信
import multiprocessing
import queue
"""
使用进程的队列实现进程间通信
"""
# def download(q):
# lis = [1,2,3]
# for i in lis:
# q.put(i)
#
# print("添加完毕")
#
#
# def manage_data(q):
# # 将队列里面的元素取出来,存到新的列表中
# man_data = list()
# while True:
# data = q.get()
# man_data.append(data)
#
# # 如果队列为空 则退出循环
# 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()
"""
如果是普通队列 可以实现吗?
"""
def download(q):
lis = [1,2,3]
for i in lis:
q.put(i)
print("添加完毕")
def manage_data(q):
# 将队列里面的元素取出来,存到新的列表中
man_data = list()
while True:
data = q.get()
man_data.append(data)
# 如果队列为空 则退出循环
if q.empty():
break
print(man_data)
def main():
# q = multiprocessing.Queue()
# 1.使用普通队列
q = queue.Queue()
p1 = multiprocessing.Process(target=download, args=(q,))
p2 = multiprocessing.Process(target=manage_data, args=(q,))
# 使用普通队列的时候 不再是使用 start()方法 启动进程 而是使用run()方法
# p1.start()
# p2.start()
# 可以执行
p1.run()
p2.run()
if __name__ == '__main__':
main()
run() 与 start() 区别
from multiprocessing import Process
import time
"""
run() 与 start() 区别
"""
def demo1():
for i in range(3):
print("--1--")
time.sleep(1)
def demo2():
for i in range(3):
print("--2--")
time.sleep(1)
if __name__ == '__main__':
p1 = Process(target=demo1)
p2 = Process(target=demo2)
# 多进程
# p1.start()
# p2.start()
# print("主程序")
# 与普通函数的调用没有什么区别 依次执行
p1.run()
p2.run()
print("主程序")
进程池
import os, time
from multiprocessing import Pool
"""
进程池
"""
def worker(msg):
# 记录开始时间
t_start = time.time()
# 打印输出 任务对应的进程Id
print(f"{msg}开始执行,进程号为{os.getpid()}")
time.sleep(2)
# 记录结束时间
t_stop = time.time()
# 输出任务耗时
print(msg, f"执行完成,耗时{t_stop - t_start}")
if __name__ == '__main__':
# 1.创建进程池
po = Pool(3)
for i in range(10):
po.apply_async(worker, (i,))
# 此时运行,只执行了主进程
print("start")
# 关闭进程池,不再接收新的请求
po.close()
# 关闭进程池 在添加 进程任务 运行报错
# po.apply_async(worker) # Pool not running
# 执行完子进程 再执行主进程
po.join()
进程池通信
import multiprocessing
"""
进程池通信
"""
def demo1(q):
try:
# 注意:进程池里面的进程,如果出现异常,并不会报出异常 而是阻塞
# 1 / 0
q.put("a")
print("--1--")
except Exception as e:
print(e)
def demo2(q):
print(q.get())
print("--2--")
if __name__ == '__main__':
# 1.进程队列通信 进程池 使用 进程队列 没有调用的 demo1 与 demo2
# q = multiprocessing.Queue()
# 1.进程池创建队列通信
q = multiprocessing.Manager().Queue()
# 2.进程池
po = multiprocessing.Pool()
# 3.添加任务
po.apply_async(demo1, args=(q,))
po.apply_async(demo2, args=(q,))
po.close()
po.join()
文件的拷贝
import multiprocessing
import os
"""
文件拷贝
"""
def copy_file(file_name, new_fold_name, old_fold_name):
# 读取file_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():
# 1.获取用户要复制的文件夹名称
old_fold_name = input("请输入要复制的文件夹名字")
# 2.创建新的文件夹
new_fold_name = old_fold_name + "附件"
# 3.判断该文件路径是否存在 不存在才 创建文件夹
if not os.path.exists(new_fold_name):
os.mkdir(new_fold_name)
# 4.获取老的文件夹 下 所有需要被拷贝文件的 名字
file_names = os.listdir(old_fold_name)
# print(file_names)
# 同步 拷贝
# 5.创建进程池
po = multiprocessing.Pool()
# 6.添加拷贝任务
for file_name in file_names:
po.apply_async(copy_file, args=(file_name, new_fold_name, old_fold_name))
po.close()
po.join()
if __name__ == '__main__':
main()
"""
实现进度条
- 1.获取到文件的总数
- 2.当前已经下载到哪个文件了
- 3. 2/3-->下载进度
"""
import multiprocessing
import os
def copy_file(q, file_name, new_fold_name, old_fold_name):
# 读取file_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)
# 将拷贝的文件放置队列
q.put(file_name)
def main():
# 1.获取用户要复制的文件夹名称
old_fold_name = input("请输入要复制的文件夹名字")
# 2.创建新的文件夹
new_fold_name = old_fold_name + "附件"
# 3.判断该文件路径是否存在 不存在才 创建文件夹
if not os.path.exists(new_fold_name):
os.mkdir(new_fold_name)
# 4.获取老的文件夹 下 所有需要被拷贝文件的 名字
file_names = os.listdir(old_fold_name)
# print(file_names)
# 同步 拷贝
# 5.创建进程池
po = multiprocessing.Pool()
# 创建队列
q = multiprocessing.Manager().Queue()
# 6.添加拷贝任务
for file_name in file_names:
po.apply_async(copy_file, args=(q, file_name, new_fold_name, old_fold_name))
po.close()
# 1.文件总数
file_count = len(file_names)
copy_file_num = 0
while True:
q.get()
copy_file_num += 1
# %f %2.f --> 保留两位小数 %%-->为了显示百分号
print("拷贝进度%2.f%%"%(copy_file_num*100/file_count))
if copy_file_num >= file_count:
break
po.join()
if __name__ == '__main__':
main()