Python Process多进程实现过程


Posted in Python onOctober 22, 2019

进程的概念

程序是没有运行的代码,静态的;

进程是运行起来的程序,进程是一个程序运行起来之后和资源的总称;

程序只有一个,但同一份程序可以有多个进程;例如,电脑上多开QQ;

程序和进程的区别在于有没有资源,进程有资源而程序没有资源,进程是一个资源分配的基本单元;
程序在没运行的时候没有资源,没有显卡,没有网卡,等等;双击运行后有摄像头,有网速等等,就叫做进程;

进程的状态

进程状态图

Python Process多进程实现过程

  • 就绪态:运行的条件都已经慢去,正在等在cpu执行
  • 执行态:cpu正在执行其功能
  • 等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态

使用Process完成多任务

进程的使用步骤和线程的使用步骤基本一致;

进程的使用步骤:

  • 导入multiprocessing;
  • 编写多任务所所需要的函数;
  • 创建multiprocessing.Process类的实例对象并传入函数引用;
  • 调用实例对象的start方法,创建子线程。

进程使用步骤图示:

Python Process多进程实现过程

进程使用步骤代码

import time
import multiprocessing
def sing():
  while True:
    print("-----sing-----")
    time.sleep(1)
def dance():
  while True:
    print("-----dance-----")
    time.sleep(1)
def main():
  p1 = multiprocessing.Process(target=sing)
  p2 = multiprocessing.Process(target=dance)
  p1.start()
  p2.start()
if __name__ == "__main__":
  main()

运行结果:

-----sing-----
-----dance-----
-----sing-----
-----dance-----
-----sing-----
-----dance-----
......

进程:

  • 主进程有什么,子进程就会有什么资源;
  • 线程能创建多任务,进程也能创建多任务,但进程耗费的资源比较大;
  • 所以运行的进程数,不一定越多越好;
  • 当创建子进程时,会复制一份主进程的资源,代码,内存等,但又会有自己不同的地方,比如pid等;
  • 我们可以理解为多进程之间共享代码,即只有一份代码,但有多个指向同一代码的箭头;
  • 能共享的就共享,不能共享的就拷贝一份;不需要修改的就共享,要修改的时候就给你拷贝一份,这就是写时拷贝;

获取进程id

获取进程id代码

from multiprocessing import Process
import osdef run_proc():
  """子进程要执行的代码"""
  print('子进程运行中,pid=%d...' % os.getpid()) # os.getpid获取当前进程的进程号
  print('子进程将要结束...')

if __name__ == '__main__':
  print('父进程pid: %d' % os.getpid()) # os.getpid获取当前进程的进程号
  p = Process(target=run_proc)
  p.start()

进程和线程对比

进程和线程的区别

  • 进程是系统进行资源分配和调度的一个独立单位;
  • 线程是进程的一个实体,是CPU调度和分派的基本单位,即是操作系统调度的单位,它是比进程更小的能独立运行的基本单位;
  • 一个程序至少有一个进程,一个进程至少有一个线程;
  • 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高;
  • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率;
  • 线程不能够独立执行,必须依存在进程中;
  • 进程先有,才有的线程;
  • 线程用资源去做事;
  • 多线程能实现多任务是指在一个进程资源里面有多个箭头;多线程是在同一个资源里面有多个箭头执行同一份代码;
  • 多进程的多任务是又开启了一份资源,在这个资源里面又有一个箭头;
  • 进程执行方式1:在一份资源里面有多个箭头在执行;
  • 进程执行方式2:有多份资源,在每一份资源里面有一个箭头执行代码;
  • 线程执行开销小,但不利于资源的管理和保护,进程正好相反;
  • 开发中还是多线程用的多;

通过队列完成进程间通信

队列使用语法

# 创建队列:
from multiprocessing import Queue
q = Queue(3)
# 往队列中添加数据:
q.put(xxx)
# 从队列中获取数据:
q.get()

通过队列完成进程间通信代码

from multiprocessing import Queue
import multiprocessing
def download_data(q):
  """模拟这是从网上下载数据"""
  data = [11, 22, 33]
  for i in data:
    q.put(i)
  print("数据下载完成")
def deal_data(q):
  """模拟处理从网上下载下来的数据"""
  data_list = []
  while True:
    data = q.get()
    data_list.append(data)
    if q.empty():
      break
  print("处理数据结束,数据为:", data_list)
def main():
  q = Queue(3)
  p1 = multiprocessing.Process(target=download_data, args=(q,))
  p2 = multiprocessing.Process(target=deal_data, args=(q,))
  p1.start()
  time.sleep(1)
  p2.start()
if __name__ == '__main__':
  main()

运行结果:

数据下载完成

处理数据结束,数据为: [11, 22, 33]

进程池完成多任务

进程池

进程池的概念

因为进程的创建和销毁是需要大量的资源的,为了减少消耗,当我们在处理多任务时,比如100个任务,我们可以先创建10个进程,然后用这10个进程来执行者100个任务,就可以重复使用进程,达到节约资源的目的了,而这个就可以使用进程池。

进程池的创建

任务数固定且较少,用普通的进程即可;任务数不确定,且比较多,就用进程池;

进程池不会等待进程执行完毕,我们需要使用po.join()让主进程等待进程池中的进程执行完;且po.close()必须在join前面;小编整理一套Python资料和PDF,有需要Python学习资料可以加学习群:631441315 ,反正闲着也是闲着呢,不如学点东西啦~~

创建进程池语法

# 创建进程池
from multiprocessing import Pool
po = Pool(3)

# 给进程池传递任务和参数
po.asyn(sing, (num,))

# 让进程池等待子进程执行完
po.close()
po.join()

进程池pool示例

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):
    # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
    # 每次循环将会用空闲出来的子进程去调用目标
    po.apply_async(worker, (i,))

  print("----start----")
  po.close() # 关闭进程池,关闭后po不再接收新的请求
  po.join() # 等待po中所有子进程执行完成,必须放在close语句之后
  print("-----end-----")
if __name__ == '__main__':
  main()

执行结果:

----start----
0开始执行,进程号为7812
1开始执行,进程号为9984
2开始执行,进程号为1692
执行完毕,耗时0.65
3开始执行,进程号为9984
执行完毕,耗时1.08
4开始执行,进程号为7812
执行完毕,耗时1.82
5开始执行,进程号为1692
执行完毕,耗时1.12
6开始执行,进程号为7812
执行完毕,耗时1.35
7开始执行,进程号为9984
执行完毕,耗时0.11
8开始执行,进程号为9984
执行完毕,耗时0.50
9开始执行,进程号为7812
执行完毕,耗时0.65
执行完毕,耗时0.70
执行完毕,耗时0.74
-----end-----

多进程拷贝文件夹

多任务文件夹copy

步骤思路:

1.获取用户要拷贝的文件夹的名字;

2.创建一个新的文件夹;

3.获取文件夹的所有待拷贝的文件名;listdir()

4.创建进程池;

5.复制原文件夹中的文件,到新文件夹的文件中去;

多任务拷贝文件代码

import os
from multiprocessing import Pool
def copy_file(file, old_folder, new_folder):

  old_f = open(old_folder+"/"+file, "rb")
  data = old_f.read()
  old_f.close()

  new_f = open(new_folder+"/"+file, "wb")
  new_f.write(data)
  new_f.close()
  print("创建文件成功:", file)
def main():
  # 1.获取要拷贝的文件夹
  old_folder = input("请输入你要拷贝的文件夹:")
  # 2.创建新文件夹
  new_folder = old_folder + "_复件"
  try:
    os.mkdir(new_folder)
    print("创建文件夹成功")
  except Exception as e:
    pass
  # 3.获取文件夹中所有待拷贝的文件,listdir()
  files_list = os.listdir(old_folder)
  # print(files_list)
  # 4.创建进程池
  po = Pool(5)
  for file in files_list:
    # 向进程池中添加复制文件的任务
    po.apply_async(copy_file, args=(file, old_folder, new_folder))
  # 复制原文件夹中的文件,到新文件夹中
  po.close()
  po.join()
if __name__ == '__main__':
  main()

在完成文件夹拷贝后,增加了一个需求,显示拷贝文件的进度条,怎么办?

多任务拷贝文件并显示进度条

如果要在进程池中使用Queue,要使用from multiprocessing import Manager ,使用Manager().Queue();

显示进度条思路:

  • 创建一个队列;
  • 往拷贝文件的函数中传入队列,拷贝好一个文件就往q中传入该文件名;
  • 在主函数中计算listdir()中的所有文件数量;
  • 在主函数中定义一个num,初始值为0;
  • 在主函数中定义一个while true,从q中获取文件每获取一个文件们就将num+1
  • 计算,如果num的值大于等于总文件数量,就break;
  • 使用已拷贝文件数量num除以总文件数量,即为拷贝的进度,使用开头\r 和end=""让显示进度不换行,如下:

print("\r已拷贝文件%.2f %%" % (copy_ok_file_num*100/all_file_len), end="")

多任务拷贝文件并显示进度条代码:

import os
from multiprocessing import Pool, Manager
def copy_file(q, file, old_folder, new_folder):
  old_f = open(old_folder+"/"+file, "rb")
  data = old_f.read()
  old_f.close()
  new_f = open(new_folder+"/"+file, "wb")
  new_f.write(data)
  new_f.close()
  q.put(file)
def main():
  # 1.获取要拷贝的文件夹
  old_folder = input("请输入你要拷贝的文件夹:")
  # 2.创建新文件夹
  new_folder = old_folder + "_复件"
  try:
    os.mkdir(new_folder)
    print("创建文件夹成功")
  except Exception as e:
    pass
  # 3.获取文件夹中所有待拷贝的文件,listdir()
  files_list = os.listdir(old_folder)
  # 4.创建进程池
  po = Pool(5)
  # 5.创建队列
  q = Manager().Queue()
  # 6.复制原文件夹中的文件,到新文件夹中
  for file in files_list:
    # 向进程池中添加复制文件的任务
    po.apply_async(copy_file, args=(q, file, old_folder, new_folder))
  all_file_len = len(files_list)
  po.close()
  # po.join()
  copy_ok_file_num = 0
  while True:
    file = q.get()
    copy_ok_file_num += 1
    print("已拷贝文件%.2f %%" % (copy_ok_file_num*100/all_file_len))
    # print("\r已拷贝文件%.2f %%" % (copy_ok_file_num*100/all_file_len), end="")
    if copy_ok_file_num >= all_file_len:
      break
  print()
if __name__ == '__main__':
  main()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现2014火车票查询代码分享
Jan 10 Python
python实现文件名批量替换和内容替换
Mar 20 Python
Python图像灰度变换及图像数组操作
Jan 27 Python
小议Python中自定义函数的可变参数的使用及注意点
Jun 21 Python
python实现12306火车票查询器
Apr 20 Python
详解python编译器和解释器的区别
Jun 24 Python
如何使用Python抓取网页tag操作
Feb 14 Python
Python中pyecharts安装及安装失败的解决方法
Feb 18 Python
PyCharm License Activation激活码失效问题的解决方法(图文详解)
Mar 12 Python
python实现图像外边界跟踪操作
Jul 13 Python
anaconda3安装及jupyter环境配置全教程
Aug 24 Python
解决Tkinter中button按钮未按却主动执行command函数的问题
May 23 Python
详解python中eval函数的作用
Oct 22 #Python
FFT快速傅里叶变换的python实现过程解析
Oct 21 #Python
python 采用paramiko 远程执行命令及报错解决
Oct 21 #Python
python文件读写代码实例
Oct 21 #Python
python 动态调用函数实例解析
Oct 21 #Python
python 两个数据库postgresql对比
Oct 21 #Python
python多进程(加入进程池)操作常见案例
Oct 21 #Python
You might like
本地计算机无法启动Apache故障处理
2014/08/08 PHP
phpStorm+XDebug+chrome 配置详解
2019/04/01 PHP
setTimeout和setInterval的浏览器兼容性分析
2007/02/27 Javascript
IE和Firefox下javascript的兼容写法小结
2008/12/10 Javascript
动态为事件添加js代码示例
2009/02/15 Javascript
响应鼠标变换表格背景或者颜色的代码
2009/03/30 Javascript
用document.documentElement取代document.body的原因分析
2009/11/12 Javascript
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
indexOf 和 lastIndexOf 使用示例介绍
2014/09/02 Javascript
jQuery仿Flash上下翻动的中英文导航菜单实例
2015/03/10 Javascript
JavaScript中String.prototype用法实例
2015/05/20 Javascript
jQuery绑定事件的几种实现方式
2016/05/09 Javascript
原生JS下拉加载插件分享
2016/12/26 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
2019/09/01 Javascript
Vue最新防抖方案(必看篇)
2019/10/30 Javascript
[03:11]2014DOTA2国际邀请赛-VG掉入败者组 独家专访357
2014/07/19 DOTA
[06:14]《辉夜杯》外卡赛附加赛 4支战队巡礼
2015/10/23 DOTA
Python 多线程抓取图片效率对比
2016/02/27 Python
python flask 多对多表查询功能
2017/06/25 Python
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
Django 中使用流响应处理视频的方法
2018/07/20 Python
python安装本地whl的实例步骤
2019/10/12 Python
Python爬虫爬取、解析数据操作示例
2020/03/27 Python
python文件读取失败怎么处理
2020/06/23 Python
python读取xml文件方法解析
2020/08/04 Python
基于Python采集爬取微信公众号历史数据
2020/11/27 Python
英国袜子店:Sock Shop
2017/01/11 全球购物
奥地利汽车配件店:Pkwteile.at
2017/03/10 全球购物
菲律宾领先的在线时尚商店:Zalora菲律宾
2018/02/08 全球购物
八年级生物教学反思
2014/01/22 职场文书
测控技术自荐信
2014/06/05 职场文书
群众路线教育党员自我剖析材料
2014/10/06 职场文书
2015年招聘工作总结
2014/12/12 职场文书
先进教师个人事迹材料
2014/12/15 职场文书
优秀教师个人总结
2015/02/11 职场文书
入党积极分子培养人意见
2015/06/02 职场文书