一、第一个demo
- 进程:一个程序运行起来后,代码+用到的资源 称为进程,他是操作系统非配资源的基本单元。线程完成的多任务,进程也可以
- 进程在python中使用multiprocessing模块中的Process来定义使用。
- 举例:
运行结果:"""多任务进程""" import multiprocessing import time def test1(): while True: print('---test1----') time.sleep(1) def test2(): while True: print('----test2----') time.sleep(1) def main(): """进程""" p1 = multiprocessing.Process(target=test1) p2 = multiprocessing.Process(target=test2) p1.start() p2.start() if __name__ == '__main__': main()
二、队列Queue
- 进程Queue队列:(解耦耦合性比较低) (完成数据间内容的共享)
- 导入:from multiprocessing import Queue
- 创建并规定里面最多存多少:q = Queue(X) X:是最多存多少数据
- 放数据: q.put() 取数据: q.get() get()如果空了会堵塞 put()如果满了也会堵塞
- 判断是否满了: q.full() (满的时候为true) 判断是否空了: q.empty() (空的时候为true) 返回值是True:为满/空
- 如果没有数据这个q.get_nowait()会抛出异常
- 数据类型任意
实例:模拟在网上下载东西
"""多任务 --进程 --Queue队列 进程间数据共享""" import multiprocessing from multiprocessing import Queue def download_form_web(q): """模拟从网站下载东西""" data = [11, 22, 33, 44] # 向队列中写数据 for temp in data: q.put(temp) # 输出一个写成功的提示 print("----下载器已经下载完,已将数据写入队列----") def analysis_data(q): """从队列中读取数据""" waitting = list() # 从队列中读取数据 while True: data = q.get() waitting.append(data) # 如果是空了则退出 empty:空的时候为true if q.empty(): break print(waitting) def main(): """Queue队列,进程间通信""" # 1. 创建队列 不写参数,根据计算机的硬件分配空间 q = Queue() # 2.创建多个进程将队列作为实参传入 p1 = multiprocessing.Process(target=download_form_web, args=(q, )) p2 = multiprocessing.Process(target=analysis_data, args=(q, )) # 启动进程 p1.start() p2.start() if __name__ == "__main__": main()
三、进程池Pool
当需要创建子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程,如果是上百甚至上千目标,手动的去创建进程的工作量巨大,此时就可以用multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果进程池没有满则会创建一个新的进程用来执行该请求;如果进程池满的话则需要等待,直到进程池中有进程结束,才会用之前的进程来执行新的任务。
初始化进程池:Pool(x):x为最大的进程数量
创建并调用目标函数:zpply_async(要调用的目标函数, (传递给目标的参数元组, ))
join():等待进程池中的所有进程执行完毕(要放在close()后面)
close():关闭进程池–>进程池不会在接受新的请求
os.getpid(): 查看进程号
实例:
"""进程池""" from multiprocessing import Pool import os, time, random def worker(msg): """进程池工作""" t_start = time.time() print("%s开始执行, 进程号为:%d" % (msg, os.getpid())) # random.random() 随机生成0-1之间的浮点数 time.sleep(random.random()*2) t_stop = time.time() print(msg, "执行完毕,耗时%0.2f" % (t_stop - t_start)) def main(): po = Pool(3) # 定义一个进程池,最大进程数为3 for i in range(0,10): print(f"---------{i}---------") # Pool().apply_async(要调用的目标函数, (传递给目标的参数元组, )) # 每次循环将会用空闲处理啊的子进程去调用目标 po.apply_async(worker,(i, )) print("----start----") po.close() # 关闭进程池, 关闭后po将不再接受新的请求 po.join() # 等待po中所有子进程执行完成, 必须放在close语句后面 print("----end----") if __name__ == "__main__": main()
执行结果:
四、案例:文件复制
使用进程池完成基本的功能
"""多进程案例 -- 文件夹复制""" import os import multiprocessing def copy_folder(file_name, old_folder_name, new_folder_name): """复制文件""" print("复制%s目录下的%s到%s下" % (old_folder_name, file_name, new_folder_name)) # 读文件 old_file = open(old_folder_name + '/' + file_name, 'rb') count = old_file.read() old_file.close() # 写文件 new_file = open(new_folder_name + '/' + file_name, 'wb') new_file.write(count) new_file.close() def main(): """多进程文件夹的复制""" # 获取要复制的文件夹名字 old_folder_name = input("请输入要复制的文件夹名:") # 新文件夹的名字+创建 new_folder_name = old_folder_name + "_附件" print(new_folder_name) try: # 如果已经创建会出现异常 os.mkdir(new_folder_name) except: pass # 获取文件夹中的文件 os.listdir() file_names = os.listdir(old_folder_name) # 复制文件 # 创建进程池 po = multiprocessing.Pool() for file_name in file_names: # 向进程池中添加任务 po.apply_async(copy_folder,args=(file_name, old_folder_name, new_folder_name)) po.close() po.join() if __name__ == "__main__": main()
运行结果:
使用Queue队列通信添加进度条
"""多进程案例 -- 文件夹复制 -- Queue队列通信 进度条""" import os import multiprocessing def copy_folder(q, file_name, old_folder_name, new_folder_name): """复制文件""" # print("复制%s目录下的%s到%s下" % (old_folder_name, file_name, new_folder_name)) # 读文件 old_file = open(old_folder_name + '/' + file_name, 'rb') # 写文件 new_file = open(new_folder_name + '/' + file_name, 'wb') while True: count = old_file.read(1024) if count: new_file.write(count) else: break old_file.close() new_file.close() # 写完然后向队列中传消息 q.put(file_name) def main(): """多进程文件夹的复制""" # 获取要复制的文件夹名字 old_folder_name = input("请输入要复制的文件夹名:") # 新文件夹的名字+创建 new_folder_name = old_folder_name + "_附件" # print(new_folder_name) try: # 如果已经创建会出现异常 os.mkdir(new_folder_name) except: pass # 获取文件夹中的文件 os.listdir() file_names = os.listdir(old_folder_name) # 复制文件 # 创建队列 q = multiprocessing.Manager().Queue() # 创建进程池 po = multiprocessing.Pool() for file_name in file_names: # 向进程池中添加任务 po.apply_async(copy_folder,args=(q, file_name, old_folder_name, new_folder_name)) po.close() # po.join() # 总共的文件数 file_num = len(file_names) file_num_ok = 0 # 显示进度 while True: file_name_ok = q.get() # print("%s文件已经拷贝完成" % file_name_ok) file_num_ok +=1 print("\r拷贝完成的进度:%.2f %%" % (file_num_ok*100 / file_num), end="") if file_num_ok >= file_num: break if __name__ == "__main__": main()
运行结果:
五、总结
- 进程和线程的区别:
- 定义不同:
- 进程是系统进行资源分配和调度的一个独立单位
- 线程是进程中的一个实体,是cpu调度和分派的基本单位
- 一个进程中一定包括一个线程
- 区别:
- 一个一个程序至少有一个进程,一个进程至少有一个线程
- 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发姓高
- 进程执行过程中拥有独立的内存单元,而多线程共享内存,从而极大地提高了程序的运行效率
- 线程不能单独运行,必须依存在进程中
版权声明:本文为weixin_43844838原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。