前沿:在之前的博客分享中,已經分享了 Python–使用線程–批量文件的移動 關於兩層文件的移動和複製,但是如果我們想多層的複製例如:D:\department_data_management 裏邊的而且包含很多曾文件夾,我們想原封不動的複製到F盤,此時怎麼搞?
今天就分享一下代碼,使用技術:線程+隊列。
# @Time : 2019-04-11 09:59
# @Author : xgp
# @File : file_move.py
# @Software: PyCharm
# @description:把整個文件夾以及子文件夾複製到某個位置。
"""
waring:當你複製的文件比較少的時候,可能因爲文件夾只有一個線程在執行,而文件的複製是很多線程在執行,
這樣可能導致文件夾未建立而文件卻在複製而報錯,這個時候建議在執行一次即可。所以此方法適合複製大量的文件,或者文件夾。
"""
import os
import shutil
import threading
from queue import Queue
class FileMove:
def __init__(self):
"""
一些參數的輸入
"""
self.folder_queue = Queue()
self.file_queue = Queue()
self.method = input('請選擇文件是選擇 複製 還是移動 ?eg:[複製,移動]:')
self.file_path = input(r'請輸入想要操作的文件夾eg:[D:\Image]:')
self.d_path = input(r'請輸入想要 移動\複製 到的盤符或者路徑eg:[E:, E:\image,F:,F:\image\picture]:')
self.s_path = self.file_path[:2]
def write_info(self, file_path):
"""
向隊列中寫入文件夾和文件
:param file_path:
:return:
"""
try:
all_folder = os.listdir(file_path)
except FileNotFoundError as e:
print('請正確輸入文件夾的位置.......')
else:
for each_file in all_folder:
if os.path.isdir(os.path.join(file_path, each_file)):
self.folder_queue.put(os.path.join(file_path, each_file))
elif os.path.isfile(os.path.join(file_path, each_file)):
self.file_queue.put(os.path.join(file_path, each_file))
def read_folder(self):
"""
獲取到文件夾,並在目的盤 建立文件夾,如果文件夾中還含有文件夾和文件 調用 write_info 方法繼續寫。
:return:
"""
while True:
try:
folder_path = self.folder_queue.get(timeout=3)
self.folder_queue.task_done()
except BaseException as e:
print('文件夾的獲取結束,開始下一個階段文件的複製............... %s' % str(e))
break
else:
try:
if not os.path.exists(folder_path.replace(self.file_path, self.d_path)):
os.makedirs(folder_path.replace(self.file_path, self.d_path))
except BaseException as e:
print('創建文件夾的時候出現了問題 %s' % str(e))
self.write_info(folder_path)
def read_file(self):
"""
從file隊列中拿到文件 並進行復制或者移動。
:return:
"""
while True:
try:
file_path = self.file_queue.get(timeout=3)
self.file_queue.task_done()
except BaseException as e:
print('獲取文件結束,整個流程走完.........終止 %s' % str(e))
break
else:
try:
if not os.path.exists(file_path.replace(self.file_path, self.d_path)): # 這個是你需要修改的
if self.method == "複製":
print('複製中..........')
shutil.copy(file_path, file_path.replace(self.file_path, self.d_path))
elif self.method == "移動":
print('移動中.........')
shutil.move(file_path, file_path.replace(self.file_path, self.d_path))
shutil.rmtree(self.file_path)
else:
print('暫未開放此功能........敬請期待')
break
else:
print('已經存在了')
pass
except BaseException as e:
print('複製文件的時候出錯了...............%s' % str(e))
def run(self):
"""
主邏輯開始運行。
:return:
"""
thread_list = []
info_list = threading.Thread(target=self.write_info, args=(self.file_path,))
thread_list.append(info_list)
folder_list = threading.Thread(target=self.read_folder)
thread_list.append(folder_list)
for i in range(50):
file_list = threading.Thread(target=self.read_file)
thread_list.append(file_list)
for t in thread_list:
t.setDaemon(True)
t.start()
for q in [self.folder_queue, self.file_queue]:
q.join()
print('結束')
if __name__ == '__main__':
file_move = FileMove()
file_move.run()
這只是一個簡單的 複製 和移動,你也可以在源代碼的基礎上進行修改和添加,使其功能更強,當然你也可以打包一下分享給你的朋友使用,如果運行代碼中出現一點小bug自行解決或者一起討論。