进程
进程的创建步骤
# 导入进程模块
import multiprocessing
# 创建一个进程的实例对象
p = multiprocessing.Process(target=fun_name,args=(元组),kwargs={字典})
# 创建并启动进程
p.start()
p.join() 可以阻塞主进程,等待子进程的结束
# 获取进程的pid
os.getpid()
# 获取进程的父进程的pid
os.getppid()
**进程中,主进程的父进程pid是系统产生的,子进程的父进程pid是主进程的pid,
主进程死掉,子进程不会死,子进程会有新的父进程,(这个进程的名字好像是upstart)如果继续kill掉这个进程,将锁屏。
通过Queue实现进程间通信
# 创建一个队列
q = multiprocessing.Queue(5) # 5代表队列可以接受的容量
# 向队列添加数据
q.put(data)
# 从队列中获取数据
q.get()
# 判断队列是否为空,为空返回True
q.empty()
# 判断队列中是否已满
q.full()
**注意:如果是通过进程池创建的进程,那么队列的使用要用 multiprocessing.Manager().Queue()的方式,否则会报错。
进程池Pool
# 导入进程池模块
from multiprocessing import Pool
# 定义进程池,最大进程数
po = Pool(3)
# 通过进程池调用目标 apply_async 非阻塞,不会等待子进程结束,apply 阻塞,会等待子进程结束才结束
po.apply_async(要调用的目标,(传递给目标的参数元组,))
# 关闭进程池
po.close()
# 等待进程池执行完毕
po.join()
案例
多任务通过进程池,实现目录中文件copy,若有子目录就进行递归copy
import multiprocessing
import os
import time
def copy(q, file_name, old_folder_name, new_folder_name):
"""复制文件"""
# 判断copy的是文件夹
if os.path.isdir(old_folder_name + "/" + file_name):
# 创建文件夹
try:
os.mkdir(new_folder_name + "/" + file_name)
except:
pass
# 获取其中的内容
son_file_names = os.listdir(old_folder_name + "/" + file_name)
# 遍历获取内容,递归copy
for son_file_name in son_file_names:
copy(q, son_file_name, old_folder_name + "/" + file_name, new_folder_name + "/" + file_name)
else:
# 打开要复制的文件夹
with open(old_folder_name + "/" + file_name, "rb") as f:
msg = f.read()
# 写入文件
with open(new_folder_name + "/" + file_name, "wb") as f:
f.write(msg)
q.put(file_name)
time.sleep(0.01)
def conut_file(old_folder_name):
"""通过递归统计文件个数"""
file_names = os.listdir(old_folder_name)
for file_name in file_names:
# 如果是文件夹就递归打开计数
if os.path.isdir(old_folder_name + "/" + file_name):
conut_file(old_folder_name + "/" + file_name)
else:
global file_names_num
file_names_num += 1
file_names_num = 0
def main():
"""多任务进程池复制文件"""
# 输入要复制的文件夹名
old_folder_name = input("输入要复制的文件夹\n")
# 新的文件夹名字
new_folder_name = old_folder_name + "[复件]"
# 创建新文件夹
try:
os.mkdir(new_folder_name)
except:
pass
# 递归统计文件个数
conut_file(old_folder_name)
# 获取文件夹中的内容
file_names = os.listdir(old_folder_name)
# 创建进程池
po = multiprocessing.Pool(5)
# 创建一个队列
q = multiprocessing.Manager().Queue()
for file_name in file_names:
po.apply_async(copy, args=(q, file_name, old_folder_name, new_folder_name))
# 关闭进程池
po.close()
# 显示copy进度
copy_ok = 0
while True:
# 获取一个队列中的内容
q.get()
copy_ok += 1
# 显示进度
print("\r copy已完成:%.2f%%" % (copy_ok * 100 / file_names_num), end="")
if copy_ok >= file_names_num:
break
if __name__ == '__main__':
main()
对上面代码中文件统计个数部分的改进版
import multiprocessing
import os
import time
def copy(q, file_name, old_folder_name, new_folder_name):
"""复制文件"""
# 判断copy的是文件夹
if os.path.isdir(old_folder_name + "/" + file_name):
# 创建文件夹
try:
os.mkdir(new_folder_name + "/" + file_name)
except:
pass
# 获取其中的内容
son_file_names = os.listdir(old_folder_name + "/" + file_name)
# 遍历获取内容,递归copy
for son_file_name in son_file_names:
copy(q, son_file_name, old_folder_name + "/" + file_name, new_folder_name + "/" + file_name)
else:
# 打开要复制的文件夹
with open(old_folder_name + "/" + file_name, "rb") as f:
msg = f.read()
# 写入文件
with open(new_folder_name + "/" + file_name, "wb") as f:
f.write(msg)
q.put(file_name)
time.sleep(0.01)
def main():
"""多任务进程池复制文件"""
# 输入要复制的文件夹名
old_folder_name = input("输入要复制的文件夹\n")
# 新的文件夹名字
new_folder_name = old_folder_name + "[复件]"
# 创建新文件夹
try:
os.mkdir(new_folder_name)
except:
pass
# 统计文件个数
for dirpath, dirnames, file_names in os.walk(old_folder_name):
file_names_num = len(file_names)
# 获取文件夹中的内容
file_names = os.listdir(old_folder_name)
# 创建进程池
po = multiprocessing.Pool(5)
# 创建一个队列
q = multiprocessing.Manager().Queue()
for file_name in file_names:
po.apply_async(copy, args=(q, file_name, old_folder_name, new_folder_name))
# 关闭进程池
po.close()
# 显示copy进度
copy_ok = 0
while True:
# 获取一个队列中的内容
q.get()
copy_ok += 1
# 显示进度
print("\r copy已完成:%.2f%%" % (copy_ok * 100 / file_names_num), end="")
if copy_ok >= file_names_num:
break
if __name__ == '__main__':
main()