進程池
當需要創建的子進程數量不多時,可以直接利用multiprocessing中的Process動態成生多個進程,但如果是上百甚至上千個目標,手動的去創建進程的工作量巨大,此時就可以用到multiprocessing模塊提供的Pool方法。
初始化Pool時,可以指定一個最大進程數,當有新的請求提交到Pool中時,如果池還沒有滿,那麼就會創建一個新的進程用來執行該請求;但如果池中的進程數已經達到指定的最大值,那麼該請求就會等待,直到池中有進程結束,纔會用之前的進程來執行新的任務
用進程池來實現一個文件拷貝的案例:
import multiprocessing
import time
import os
# 讀寫文件
def copy_file(temp_file_dir_path, new_dir_path, file_name):
data = None
# 讀取文件
with open(temp_file_dir_path, "rb") as f_read:
data = f_read.read()
if data:
# 寫入文件
new_dir_path += "\\" + file_name
f_write = open(new_dir_path, "wb")
f_write.write(data)
f_write.close()
time.sleep(1)
# 遞歸獲取文件
def get_copy_file(dict1, dir_path, po, new_dir_path):
"""
:param dir_path:原始文件夾路徑
:param po:進程池
:param new_dir_path:新文件夾路徑
:return:
"""
# 獲取文件夾中的所有文件
file_names = os.listdir(dir_path)
for file_name in file_names:
# 文件或者文件夾目錄
temp_file_dir_path = dir_path + "\\" + file_name
# 判斷是否是文件夾,如果是就遞歸
if os.path.isdir(temp_file_dir_path):
# 如果是文件夾直接遞歸在次掃描文件,並且將新地址重新整合,以及創建新文件夾
# 這裏不能使用加等於,因爲有多個文件夾的話將會出現不停的疊加字符串導致路徑不對
new_dest_dir_path = new_dir_path + "\\" + file_name
# print(new_dest_dir_path)
# 創建新文件夾
os.mkdir(new_dest_dir_path)
# 然後開始遞歸
get_copy_file(dict1, temp_file_dir_path, po, new_dest_dir_path)
# 判斷是否是文件,是文件就執行copy功能
elif os.path.isfile(temp_file_dir_path):
# 儲存文件名
dict1["queue"].put(file_name)
dict1["len"] += 1
# 使用進程池來copy文件
po.apply_async(copy_file, args=(temp_file_dir_path, new_dir_path, file_name))
# 進程池copy
def main():
dir_path = "D:\視頻\Python\python筆記"
new_dir_path = dir_path + "【new】"
try:
# 創建新文件夾
os.mkdir(new_dir_path)
except:
pass
# 創建進程池
po = multiprocessing.Pool(5)
# 使用queue來實現進度條
dict1 = multiprocessing.Manager().dict()
q = multiprocessing.Manager().Queue()
# 來儲存文件名和文件數量
dict1["queue"] = q
dict1["len"] = 0
print(dict1)
# 獲取要複製的文件並且複製
get_copy_file(dict1, dir_path, po, new_dir_path)
# 關閉子進程
po.close()
# 等待子進程完結後在結束主進程
# po.join()
break_count = 0
while True:
break_count += 1
file_name = dict1["queue"].get()
# 如果複製的數據數量與總數一致則表示已經複製完成,可以跳出循環
num = break_count / dict1["len"]
print(f"拷貝進度爲:%% %.2f 文件名爲:{file_name}" % (num * 100))
if dict1["len"] <= break_count:
break
print(dict1["len"])
if __name__ == "__main__":
main()
作者:阿超
原創公衆號:『Python日常筆記』,專注於 Python爬蟲等技術棧和有益的程序人生,會將一些平時的日常筆記都慢慢整理起來,也期待你的關注和阿超一起學習,公衆號回覆【csdn】優質資源。