# 制作一个可以复制文件的程序
import multiprocessing
import os
def copydir(queue_show, filename, old_dir_name, new_dir_name):
# 打开原来的文件
old_f = open(old_dir_name + "/" + filename, "rb")
# 读取内容
content = old_f.read()
old_f.close()
# 打开新文件
new_f = open(new_dir_name + "/" + filename, "wb")
# 写入内容
new_f.write(content)
new_f.close()
# 当复制完一个文件后向消息队列中传信息
queue_show.put(filename)
def main():
# 获取用户需要打印的文件夹名字
old_dir_name = input(f"请输入需要复制的目录名字:")
# 创建一个新的文件夹
# 使用try来避免文件夹名字已经存在的问题
try:
new_dir_name = old_dir_name + ".复件"
os.mkdir(new_dir_name)
except:
pass
# 获取原文件夹中所有文件名字 listdir 的返回值是一个列表
old_file_name = os.listdir(old_dir_name)
# 复制所有文件到新文件夹中
# 用到进程池来进行复制
po = multiprocessing.Pool(5)
queue_show = multiprocessing.Manager().Queue()
for filename in old_file_name:
po.apply_async(copydir, args=(queue_show, filename, old_dir_name, new_dir_name))
po.close()
# 通过消息队列的方式显示复制进度
# po.join()
all_file_num = len(old_file_name)
copy_comp_num = 0
while True:
queue_show.get()
copy_comp_num += 1
print(f'\r复制进度为 %.2f %%' %(copy_comp_num*100/all_file_num), end="")
if copy_comp_num >= all_file_num:
break
print("")
if __name__ == "__main__":
main()
通过这段代码学习到的点:
1.进程池pool的使用:
使用进程池可以减少系统为新进程创建资源的过程从而加快执行速度。
进程池在关闭以后需要加上po.join来确保进程全部执行完毕
进程池中进程执行失败也不会有报错
2.os 模块的使用:
os.listdir 会将文件夹中的文件名字以列表的形式返回
os.mkdir可以用来创建文件夹
3.如何复制文件:
以读的方式打开旧文件,再以写的方式打开新文件,写入内容。
记住新旧文件打开后保存的对象之后都要关闭。
打开文件时的路径是以代码所在的位置为起始路径的。
4.如何实现进度条:
通过消息队列,完成一个进程以后在进程结束前向消息队列中写入一个信息,然后再由闲置的主进程读取消息队列,并计数,最后对比需完成的任务数与消息数来保证所有任务完成。
如果不添加条件判断,消息队列空了以后进程会堵住。
进程池之间进程想要通过消息队列通信的话,需要用到multiprocessing.Manager().Queue() 来创建消息队列。
5.python基础回顾:
print("%.2f" %变量) 来让变量保留两位小数
print(end="") 来让print打印的数据不空行,默认空行\n ,还可以空四格\t
print("\r")让打印的数据回到行首
print(“%%”)两个% 往打印的文字中添加一个%号