python多进程拷贝文件

Python多进程拷贝

实现思路

  1. 创建可获取目标文件或文件夹中的所有文件夹和文件的列表的函数
  2. 创建拷贝文件的函数
  3. 主函数创建进程池和消息队列

获取文件夹和文件列表

先判断路径是文件还是文件夹,是文件直接添加至文件列表;文件夹的话,添加至文件夹列表,利用os.listdir()函数列出当前文件夹内的所有文件,循环遍历,拼接源地址,然后作为参数递归循环;

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_file_list(source_path):
"""
遍历该文件夹中的所有文件和文件夹
获取源文件夹中的文件夹、文件列表
"""
if os.path.isdir(source_path):
S_Dir_List.append(source_path)
for temp in os.listdir(source_path):
# 拼接源地址+文件名,变成新地址,再进行递归
new_source_path = os.path.join(source_path, temp)
get_file_list(new_source_path)
else:
S_File_List.append(source_path)

拷贝文件

传入的参数

  • queue: 消息队列,用于主函数计数
  • source_file: 源文件路径
  • dest_file: 目标文件的路径

循环读取写入,是防止文件过大,读写卡死

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def copy_file(queue, source_file, dest_file):
"""
复制文件从源文件
"""
try:
fr = open(source_file,"rb")
fw = open(dest_file,"wb")
except Exception as e:
print("error:" + str(e))
else:
while True:
content = fr.read(4096)
if not content:
break
fw.write(content)
fr.close()
fw.close()
# 将文件名传入队列消息,代表复制完成
queue.put(source_file)

源代码

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from multiprocessing import Manager, Pool
import os
import time

# 源文件列表 文件夹列表
S_File_List = []
S_Dir_List = []


def get_file_list(source_path):
"""
遍历该文件夹中的所有文件和文件夹
获取源文件夹中的文件夹、文件列表
"""
if os.path.isdir(source_path):
S_Dir_List.append(source_path)
for temp in os.listdir(source_path):
# 拼接源地址+文件名,变成新地址,再进行递归
new_source_path = os.path.join(source_path, temp)
get_file_list(new_source_path)
else:
S_File_List.append(source_path)

def copy_file(queue, source_file, dest_file):
"""
复制文件从源文件
"""
try:
fr = open(source_file,"rb")
fw = open(dest_file,"wb")
except Exception as e:
print("error:" + str(e))
else:
while True:
content = fr.read(4096)
if not content:
break
fw.write(content)
fr.close()
fw.close()
# 将文件名传入队列消息,代表复制完成
queue.put(source_file)

def main():
# 获取源文件夹中的所有文件和文件夹
source_path = input("请输入要拷贝的源文件路径:")
get_file_list(source_path)

# 创建目标文件夹
dest_path = source_path + "-[复件]"
for sour_dir in S_Dir_List:
# 替换文件的路径
dest_dir = sour_dir.replace(source_path, dest_path)

try:
os.mkdir(dest_dir)
except Exception as e:
print("error" + str(e))

# 创建进程池
pool = Pool(5)
queue = Manager().Queue() # 创建队列消息用来计数


for sour_file in S_File_List:
# 替换文件的路径
dest_file = sour_file.replace(source_path,dest_path)
# print(dest_file)
# 往进程池添加任务
pool.apply_async(copy_file, args=(queue, sour_file, dest_file))
pool.close() # 关闭进程池
pool.join() # 等待子进程结束

# 显示复制文件的进度
filesNums = len(S_File_List)
COUNT = 0
while True:
queue.get()
COUNT += 1
Rate = COUNT/filesNums
print("\r当前进度: %.2f%%"%(Rate*100), end='')
if Rate >= 1:
break
print("\n...Done")
if __name__ == '__main__':
main()