Python基础 - 多进程(下)
上篇主要对多任务从生活上来认识, 同时引入对 进程 的认识, 即操作系统资源分配的基本单元. 然后通过对 并发, 并行 概念的认识, 去理解 任务调度. 然后用内置的 multiprocessing 模块来实现多任务的基本操作过程, 大致为:
创建多个任务 --> 为每个任务创建一个进程 --> 启动进程
注意参数的两种传递方式: args=(a,b, c...) 和 kwargs=
还留了一个问题, 关于多进程之前 不能共享全局变量, 而其实要解决这个问题, 就通过一个消息队列(Queue) 来实现消息的传递哦.
主进程 - 等待所有子进程
即多线程的一个默认特性是, 主进程会等待所有的子进程结束后, 才会结束哦.
import os
import time
import multiprocessing
def task_01(n):
for i in range(n):
print("task_01 is working...")
time.sleep(0.5)
if __name__ == '__main__':
# 创建子进程
p1 = multiprocessing.Process(target=task_01, args=(3,))
p1.start()
# 主进程等待
time.sleep(1)
print('主进程执行完毕...')
task_01 is working...
task_01 is working...
主进程执行完毕...
task_01 is working...
这里发现, 主进程是要等待所有的子进程都执行结束后, 才会真正结束哦,
守护主进程
即当主进程结束的时候, 杀掉所有的子进程, 即设置进程的属性 de
import os
import time
import multiprocessing
def task_01(n):
for i in range(n):
print("task_01 is working...")
time.sleep(0.5)
def task_02(n):
for i in range(n):
print('task_02 is working..')
time.sleep(0.2)
if __name__ == '__main__':
# 创建子进程
p1 = multiprocessing.Process(target=task_01, args=(3,))
p2 = multiprocessing.Process(target=task_02, args=(3,))
p1.daemon = True # 设置为守护主进程
# p2.daemon = True
p1.start()
p2.start()
# 主进程等待
time.sleep(1)
print('主进程执行完毕...')
# p2.terminate()
task_01 is working...
task_02 is working..
task_02 is working..
task_02 is working..
task_01 is working...
主进程执行完毕...
设置为守护主进程, 这样就比较灵活一下, 能适应各种业务场景.
消息队列Queue
用来解决, 进程之间的通信的哦.
import time
import multiprocessing
def add_data(queue):
for i in range(5):
if queue.full():
print("queue is full")
break
queue.put(i)
time.sleep(0.1)
print('add cur_data:', i)
def get_data(queue):
while True:
if queue.qsize() == 0:
print('queue is None')
break
print(f"get cur_data: {queue.get()}")
if __name__ == '__main__':
# 创建消息队列
queue = multiprocessing.Queue(3)
# 创建各自的进程
p_add = multiprocessing.Process(target=add_data, args=(queue,))
p_get = multiprocessing.Process(target=get_data, args=(queue,))
p_add.start()
p_add.join() # 主进程等 p_add 执行完后再执行
p_get.start()
add cur_data: 0
add cur_data: 1
add cur_data: 2
queue is full
get cur_data: 0
get cur_data: 1
get cur_data: 2
queue is None
进程池 Pool
之前的方式是, 可以为任务手动用 Process 来创建多个进程, 但当任务量是, 几千几万个是, 手动来弄, 似乎有手写难搞. 进程池就是基于这样的场景下, 自动根据任务数量而创建最合理的进程数, 这样不仅不仅场景变多了, 而且能合理利用资源, 更为重要一点, 我感觉是写代码上, 真的非常简洁优雅.
而基本的流程, 在我们初始化 Pool 时候, 可以手动指定一个最大的进程数 (超参数), 当新的请求提交到 Pool 的时候, 如果池没有满, 则创建一个新的进程来执行该请求;
而当池子是满的, 即池子中的进程数已经达到了最大值, 则 请求会自动等待, 直到池子中有空闲资源, 然后就该任务就加入进程池. 这感觉还挺智能的, 说实话.
同步任务
任务一个接一个地完成. 即下一个任务要等上一个任务跑完后才能再继续执行哦.
同步 vs 异步
- 生活中, 同步, 多个任务一起跑;
- 编程中, 同步, 多个任务按顺序跑; 异步同时执行多任务, 不等待
import time
import multiprocessing
def send_email():
print("send_email ...", multiprocessing.current_process().pid)
time.sleep(1)
if __name__ == '__main__':
# 创建Pool 并设置最大进程数
pool = multiprocessing.Pool(3)
# 大批量任务哦
for i in range(6):
pool.apply(send_email)
# 同步执行任务,要等一个任务完,再执行另一个, 别混淆跟 多进程.
send_email ... 15348
send_email ... 14928
send_email ... 7156
send_email ... 15348
send_email ... 14928
send_email ... 7156
异步任务
这厉害了, 就是多个任务同时执行, 且多进程, 这个效率就非常高呀.
import time
import multiprocessing
def send_email(n):
print("send_email ...", multiprocessing.current_process().pid)
time.sleep(1)
if __name__ == '__main__':
# 创建Pool 并设置最大进程数
pool = multiprocessing.Pool(3)
# 大批量任务哦
for i in range(6):
# apply_async: 异步, 执行顺序是Pool自己调度哦
pool.apply_async(send_email, args=(i, ))
pool.close() # 关闭进程池
pool.join() # 等待所有任务执行完成
send_email ... 8096
send_email ... 14520
send_email ... 9324
send_email ... 8096
send_email ... 14520
send_email ... 9324
我是感觉, 这个异步任务, 其顺序自己调度, 有点东西哦. 在工作中, 用异步的情景有, 之前有批量处理文件, 几千个嘛, 表字段差不多的, 需求是对每个文件进行判断, 里面的某个字段的值是否为 xxx . 在这 1000 个文件中, 先处理谁, 后处理谁是没有关系的, 因此就异步呗. 还有一个异步场景是, 爬虫 , 大批量的 url 等着被请求解析, 当然用异步啦.
同步任务. 目前我好像是很少用哦. 主要是我的一些数据处理, 分析的一些活吧, 大多都比较简单, 就读取个数据, 写写简单的 sql, 用 用pandas啥的, 就能满足了, 用的不是太多哦.
小结
- 理解多任务, 多进程, 在生活和工作中是很常见. 通俗即多个任务一起跑, 真正的其实是cpu的任务调度
- 多进程之间不能共享全局变量, 可通过消息队列来通信
- 主进程默认是等子进程结束才结束, 可对子进程设置 daemon 属性来守护主进程; join() 则是等待子进程
- 进程池用于多任务量, 自动创建合理进程的场景, 主要用同步(顺序) 任务 和 异步任务两种方式.
感觉多进程, 到这差不多了, 基本概念理清楚, 然后能用就行, 也是做个笔记, 主要是为方便后面 copy 代码而已, 嗯, 后面是可以添加一几个小案例. 多任务, 除了多进程, 还有多线程, 协程这样的概念, 一个个都会有的.
哦, 今天是2020年2月29日, 闰年哦, 希望4年后的今天, 我已经变成了数据大牛, 知识大牛. 也需个愿, 并坚持每日学习不怠.
Python基础 - 多进程(下)的更多相关文章
- 吾八哥学Python(四):了解Python基础语法(下)
咱们接着上篇的语法学习,继续了解学习Python基础语法. 数据类型大体上把Python中的数据类型分为如下几类:Number(数字),String(字符串).List(列表).Dictionary( ...
- Python基础(下)
前言 print("\n".join([''.join(['*'*((x-y)%3) if((x*0.05)**2+(y*0.1)**2 -1)**3-(x*0.05)**2*(y ...
- python基础15下_迭代器_生成器
print(dir([])) #告诉我列表拥有的所有方法 # 双下方法 # print([1].__add__([2])) print([1]+[2]) ret = set(dir([]))& ...
- python基础===多进程
进程线程的区别在进程,线程,协程的区别 linux或者unix有fork()函数,但是不支持win系统. multiprocessing multiprocessing模块是跨平台版本的多进程模块.支 ...
- Python基础Day1—下
六.Python运行 print() 打印命令,输出到屏幕上 操作: 命令提示符-->输入Python-->文件路径 若输入Python回车报错或者提示没有,则Python解释器没有安 ...
- python学习笔记(11)--测验3: Python基础语法(下) (第7周)
斐波那契数列计算 B 描述 斐波那契数列如下: F(0) = 0, F(1) = 1 F(n) = F(n-1) + F(n-2) 编写一个计算斐波那契数列的函数,采用递归方式,输出不超过n的所有斐波 ...
- Python基础知识(Basic knowledge)
Python基础知识(Basic knowledge) 1.认识Python&基础环境搭建 2.Python基础(上) 3.Python基础(中) 4.Python基础(下) 5.Python ...
- python中多进程+协程的使用以及为什么要用它
前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重.切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL, ...
- Python基础(1) - 初识Python
Python 特点: 1)面向对象 2)解释执行 3)跨平台.可移植 4)垃圾回收机制 5)动态数据类型.强类型 6)可扩展.可嵌入 Python可以方便调用C/C++等语言,同时也可以方便的被C/C ...
- python基础——面向对象进阶下
python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...
随机推荐
- 安川MOTOMAN机器人NX100维修的注意事项
安川MOTOMAN机器人NX100维修,操作人员安全注意事项 整个机器人的最大动作范围内均具有潜在的危险性. 为机器人工作的所有人员 (安全管理员.安装人员.操作人员和机器人维修人员) 必须时刻树 ...
- 解决easyexcel合并单元格数组求和重复问题
背景 EasyExcel(根据条件动态合并单元格的重复数据))_Violet-CSDN博客_easyexcel动态合并单元格现有的订单导出是使用的easyExcel完成的.对于相同单元格的合并是自定义 ...
- intellij debug模式提示 Method breakpoints may dramatically slow down debugging 解决办法
直接上图........ 点击图中按钮 或者 快捷键(Ctrl - Shift -F8 ) 出现下图
- 【BUUCTF】HardSQL
[BUUCTF]HardSQL 题目来源 收录于:BUUCTF 极客大挑战 2019 题目描述 一道纯粹的SQL注入题 尝试进行注入,发现对以下字符进行了过滤: = %20(空格) %09 %0a % ...
- Windows编程----结束进程
进程有启动就有终止,通过CreateProcess函数可以启动一个新的子进程,但是如何终结子进程呢?主要有四种方法: 通过主线程的入口函数(main函数.WinMain函数)的return关键字终止进 ...
- 修改npm下载地址为淘宝镜像
修改 npm 下载地址 修改为国内淘宝镜像 # 修改为新淘宝镜像(推荐) npm config set registry https://registry.npmmirror.com/ # 旧 npm ...
- css px em rem % vw vh vm 区别
前言 在传统项目开发中,我们只会用到 px.%.em 这几个单位长度,它们可以适用大部分项目的开发,并且拥有较好的兼容性. 而从 css3 开始,浏览器对逻辑单位的支持又提升了新的境界,增加了 rem ...
- Jenkins合并代码Git报错处理过程
#jenkins合并代码时候报错内容#10:36:08 ! [rejected] HEAD -> master (non-fast-forward)#10:36:08 error: failed ...
- FDMemtable如何增加一条自身复制的记录
procedure TFrame_Bill.CopyARecord; var lAFDmemtable : TFDMemTable; begin {$REGION '增加一条复制的记录'} try l ...
- DevOps常用工具网址
Linux基础和命令: shell语法查询: http://www.linux6.comhttps://www.tutorialspoint.com/linux_admin/index.htm 正则表 ...