Python网络编程 —— 进程
个人独立博客:www.limiao.tech
微信公众号:TechBoard
进程
进程:通俗理解就是一个运行的程序或者软件,进程是操作系统资源分配的基本单位
一个程序至少有一个进程,一个进程至少有一个线程,多进程可以完成多任务
进程的状态
工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态
进程的使用
导入进程模块:
import multiprocessing
用进程完成多任务
import multiprocessing
import time
def sing():
for i in range(10):
print("唱歌中...")
time.sleep(0.2)
def dance():
for i in range(10):
print("跳舞中...")
time.sleep(0.2)
if __name__ == "__main__":
# 创建对应的子进程执行对应的任务
sing_process = multiprocessing.Process(target=sing)
dance_process = multiprocessing.Process(target=dance)
# 启动进程执行对应的任务
sing_process.start()
dance_process.start()
Process类参数介绍
import multiprocessing
import os
def show_info(name,age):
print("show_info:", multiprocessing.current_process())
# 获取进程的编号
pritn("show_info pid:", multiprocessing.current_process().pid, os.getpid)
print(name, age)
if __name__ == "__main__":
# 创建子进程
# group: 进程组,目前只能使用None
# target: 执行的目标任务
# args: 以元组方式传参
# kwargs: 以字典方式传参
sub_prcess = multiprocessing.Process(group=None, target=show_info, arg=("杨幂", 18))
sub_prcess.start()
进程之间不共享全局变量
import multiprocessing
import time
# 全局变量
g_list = []
# 添加数据
def add_data():
for i in range(15):
g_list.append(i)
time.sleep(0.1)
print("add_data:", g_list)
# 读取数据
def read_data():
print("read_data:", g_list)
if __name__ == "__main__":
# 创建添加数据的子进程
add_process = multiprocessing.Process(target=add_data)
# 创建读取数据的子进程
read_process = multiprocessing.Process(target=read_data)
# 启动进程
add_process.start()
# 主进程等待添加数据的子进程执行完成以后再执行读取进程的操作
add_process.join()
# 代码执行到此说明添加数据的子进程把任务执行完成了
read_process.start()
创建子进程其实就是对主进程资源的拷贝
主进程会等待所有的子进程执行完成程序再退出
import multiprocessing
import time
# 工作任务
def work():
for i in range(10):
print("工作中...")
time.sleep(0.3)
if __name__ == "__main__":
# 创建子进程
sub_prcess = multiprocessing.Process(target=work)
# 查看进程的守护状态
# print(sub_prcess.daemon)
# 守护主进程,主进程退出子进程直接销毁,不再执行子进程里面的代码
# sub_prcess.daemon = True
# 启动进程执行对应的任务
sub_process.start()
# 主进程延时1s
time.sleep(1)
print("主进程执行完了")
# 主进程退出之前把所有的子进程销毁
sub_prcess.terminate()
exit()
总结: 主进程会等待所有的子进程执行完成程序再退出
获取进程pid
# 获取进程pid
import multiprocessing
import time
import os
def work():
# 获取当前进程编号
print("work进程编号:", os.getpid())
# 获取父进程编号
print("work父进程编号:", os.getppid())
for i in range(10):
print("工作中...")
time.sleep(1)
# 扩展:根据进程编号杀死对应的进程
# os.kill(os.getpid(), 9)
if __name__ == '__main__':
# 获取当前进程的编号:
print("当前进程编号:", multiprocessing.current_process().pid)
# 创建子进程
sub_process = multiprocessing.Process(target=work)
# 启动进程
sub_process.start()
# 主进程执行打印信息操作
for i in range(20):
print("我在主进程中执行...")
time.sleep(1)
运行结果:
当前进程编号: 624
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
work进程编号: 1312
work父进程编号: 624
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
***Repl Closed***
进程间通信——Queue
可以使用multiprocessing模块Queue实现多进程之间的数据传递,Queue本身是一个消息队列程序
import multiprocessing
if __name__ == "__main__":
# 创建消息队列
# 3:表示消息队列的最大个数
queue = multiprocessing.Queue(3)
# 存放数据
queue.put(1)
queue.put("hello")
queue.put([1, 5, 8])
# 总结:队列可以放入任意类型的数据
# queue.put("xxx": "yyy")
# 放入消息的时候不会进行等待,如果发现队列满了不能放入数据,那么会直接崩溃
# 建议: 放入数据统一使用 put 方法
# queue.put_nowait(("xxx": "yyy"))
# 判断队列是否满了
result = queue.full()
print(result)
# 判断队列是否为空,不靠谱(加延时可解决)
result = queue.empty()
print("队列是否为空:", result)
# 获取队列消息个数
size = queue.qsize()
print("消息个数:", size)
# 获取队列中的数据
res = queue.get()
print(res)
# 如果队列空了,那么使用get方法会等待队列有消息以后再取值
消息队列Queue完成进程间通信的演练
import multiprocessing
import time
# 添加数据
def add_data(queue):
for i in range(5):
# 判断队列是否满了
if queue.full():
# 如果满了跳出循环,不再添加数据
print("队列满了")
break
queue.put(i)
print("add:", i)
time.sleep(0.1)
def read_data(queue):
while True:
if queue.qsize == 0:
print("队列空了")
break
result = queue.get()
print("read:", result)
if __name__ == "__main__":
# 创建消息队列
queue = multiprocessing.Queue(3)
# 创建添加数据的子进程
add_process = multiprocessing.Process(target=add_data, args=(queue,))
# 创建读取数据的子进程
read_process = multiprocessing.Process(target=read_data, args=(queue,))
# 启动进程
add_process.start()
# 主进程等待写入进程执行完成以后代码再继续往下执行
add_process.join()
read_process.start()
进程池Pool
进程池的概念
池子里面放的是进程,进程池会根据任务执行情况自动创建进程,而且尽量少创建进程,合理利用进程池中的进程完成多任务
当需要创建的子进程数量不多时,可以直接利用multiprocess中的Process动态生成多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocess模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求,但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
进程池同步执行任务
进程池同步执行任务表示进程池中的进程在执行任务的时候一个执行完成另外一个才能执行,如果没有执行完会等待上一个进程执行
进程池同步实例代码
import multiprocessing
import time
# 拷贝任务
def work():
print("复制中...", multiprocessing.current_process().pid)
time.sleep(1)
if __name__ == '__main__':
# 创建进程池
#3:进程池中进程的最大个数
pool = multiprocessing.Pool(3)
# 模拟大批量的任务,让进程池去执行
for i in range(5):
# 循环让进程池执行对应的work任务
# 同步执行任务,一个任务执行完成以后另外一个任务才能执行
pool.apply(work)
运行结果:
复制中... 6172
复制中... 972
复制中... 972
复制中... 1624
复制中... 1624
***Repl Closed***
进程池异步执行任务
进程池异步执行任务表示进程池中的进程同时执行任务,进程之间不会等待
进程池异步实例代码
import multiprocessing
import time
# 拷贝任务
def work():
print("复制中...", multiprocessing.current_process().pid)
# 获取当前进程的守护状态
# 提示:使用进程池创建的进程时守护主进程的状态,默认自己通过Process创建的进程是不守护主进程的状态
# print(multiprocessing.current_process().daemon)
time.sleep(1)
if __name__ == '__main__':
# 创建进程池
# 3:进程池中进程的最大个数
pool = multiprocessing.Pool(3)
# 模拟大批量的任务,让进程池去执行
for i in range(5):
# 循环让进程池执行对应的work任务
# 同步执行任务,一个任务执行完成以后另外一个任务才能执行
# pool.apply(work)
# 异步执行,任务执行不会等待,多个任务一起执行
pool.apply_async(work)
# 关闭进程池,意思告诉主进程以后不会有新的任务添加进来
pool.close()
# 主进程等待进程池执行完成以后程序再退出
pool.join()
运行结果:
复制中... 1848
复制中... 12684
复制中... 12684
复制中... 6836
复制中... 6836
***Repl Closed***
个人独立博客:www.limiao.tech
微信公众号:TechBoard

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
BAT等公司必问的8道Java经典面试题,你都会了吗?
工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1、“知其然不知其所以然”。做了多年技术,开发了很多业务应用,但似乎并未思考过种种技术选择背后的逻辑。坦白说,我并不放心把具有一定深度的任务交给他。 2、知识碎片化,不成系统。在面试中,面试者似乎无法完整、清晰地描述自己所开发的系统,或者使用的相关技术。平时可能埋头苦干,或者过于死磕某个实现细节,并没有抬头审视这些技术。 前人已经掉过的坑,后来的同学就别再“前仆后继”了! Java基础 1、谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 考点分析: 对于这类笼统的问题,你需要尽量表现出自己的思维深入并系统化,Java 知识理解得也比较全面,一定要避免让面试官觉得你是个“知其然不知其所以然”的人。毕竟明白基本组成和机制,是日常工作中进行问题诊断或者性能调优等很多事情的基础,相信没有招聘方会不喜欢“热爱学习和思考”的面试者。 回归正题,对于 Java 平台的理解,可以从很多方面简明扼要地谈一下,例如:Java 语言特性,包括泛型、Lam...
-
下一篇
Python网络编程——协程
个人独立博客:www.limiao.tech 微信公众号:TechBoard 协程的概念 协程,又称微线程,纤程,也称用户级线程,在不开辟线程的基础上实现多任务,也就是在单线程的情况下完成多任务,多个任务按照一定顺序交替执行的,通俗理解只要在def里面只看到一个yield关键字表示就是协程 协程也是实现多任务的一种方式 协程yield的代码实现 简单实现协程 import time # 定义协程 def work1(): while True: print("work1...") time.sleep(1) yield def work2(): while True: print("work2...") time.sleep(1) yield if __name__ == '__main__': g1 = work1() g2 = work2() while True: next(g1) next(g2) 实现协程的第二种方式:greenlet greenlet介绍:为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变得更加简单 首先使用pip...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 面试大杂烩
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果