Python之多线程与多进程(二)
多进程
上一章:Python多线程与多进程(一)
由于GIL的存在,Python的多线程并没有实现真正的并行。因此,一些问题使用threading模块并不能解决
不过Python为并行提供了一个替代方法:多进程。在多进程里,线程被换成一个个子进程。每个进程都运作着各自的GIL(这样Python就可以并行开启多个进程,没有数量限制)。需要明确的是,线程都是同一个进程的组成部分,它们共享同一块内存、存储空间和计算资源。而进程却不会与它们的父进程共享内存,因此进程间通信比线程间通信更为复杂
多进程相比多线程优缺点如下:
优点 | 缺点 |
可以使用多核操作系统 | 更多的内存消耗 |
进程使用独立的内存空间,避免竞态问题 | 进程间的数据共享变得更加困难 |
子进程容易中断 | 进程间通信比线程困难 |
避开GIL限制 |
Python多进程
multiprocessing模块提供了一个Process类,它有点类似多线程模块中threading.Thread类。因此,把多线程代码迁移到多进程还是比较简单的,因为代码的基本结构不变
我们快速演示一个多进程的示例:
import multiprocessing def run(pname):
print(pname) for i in range(3):
p = multiprocessing.Process(target=run, args=("Process-%s" % i,))
p.start()
p.join()
运行结果:
Process-0
Process-1
Process-2
可以看出,多进程和多线程的代码非常像,这里需要注意一点,如果是在Windows上执行的需要把启动进程的代码放到if __name__ == "__main__":底下
if __name__ == "__main__":
for i in range(3):
p = multiprocessing.Process(target=run, args=("Process-%s" % i,))
p.start()
p.join()
进程退出状态:当进程结束的时候,会产生一个状态码,它是一个数字,表示执行结果,不同数字代表程序运行的不同情况:
- 等于0表示正常完结
- 大于0表示异常完结
- 小于0表示进程被另一个进程通过-1*exit_code信号终结
下面的代码演示如何读取和使用退出码
import multiprocessing
import time def first():
print("There is no problem here") def second():
raise RuntimeError("Error raised!") def third():
time.sleep(3)
print("This process will be terminated") workers = [multiprocessing.Process(target=first), multiprocessing.Process(target=second),
multiprocessing.Process(target=third)]
for w in workers:
w.start() workers[-1].terminate() for w in workers:
w.join() for w in workers:
print(w.exitcode)
运行结果:
There is no problem here
Process Process-2:
Traceback (most recent call last):
File "/home/lf/anconda3/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/home/lf/anconda3/lib/python3.6/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "test01.py", line 11, in second
raise RuntimeError("Error raised!")
RuntimeError: Error raised!
0
1
-15
我们注意到,第三个子进程的print语句没有执行,这是因为在sleep方法结束之前进程已经被中止了。还有一点需要注意的是:两个独立的for循环处理三个子进程:一个启动子进程,另一个通过join方法连接进程。如果我们在开启每个子进程时都执行join方法,而不是没有join直接中断第三个进程,那么第三个进程就不会失败。于是第三个子进程返回的退出码也是0,因为和多线程一样,join方法在目标进程完结之前会阻塞子进程的调用
进程池
多进程模块还提供了pool类,表示一个进程池,里面装有子进程,可以通过不同的方法执行同一组任务。
Pool类的主要方法如下:
- apply:这个方法在独立的子进程中运行一个函数。它还会在被调用函数返回结果之前阻塞进程
- apply_async:这个方法会在独立子进程中异步地运行一个函数,就是说进程会立即返回一个ApplyResult对象,要获得真实的返回值需要使用get()方法。get()在异步执行的函数结束之前都会被阻塞
- map:这个方法对一组数值应用一个函数。它是一个阻塞动作,所以返回值是每个值经过函数映射的列表
进程间通信:进程间通信的方式不像线程间通信那么简单,但是,Python提供了一些工具帮助我们解决问题。
Queue类是一个既线程安全又进程安全的先进先出(FIFO)数据交换机制。multiprocessing提供的Queue类基本是Queue.Queue的克隆版本,因此二者API基本相同
from multiprocessing import Queue, Process
import random def generate(q):
while True:
value = random.randrange(10)
q.put(value)
print("Value added to queue: %s" % (value)) def reader(q):
while True:
value = q.get()
print("Value from queue: %s" % (value)) queue = Queue()
p1 = Process(target=generate, args=(queue,))
p2 = Process(target=reader, args=(queue,))
p1.start()
p2.start()
Pipe方法:Pipe(管道)方法为两个进程提供了一种双向通信的机制,Piped()函数返回一对连接对象,每个对象表示管道的一端。每个连接对象都有send()和recv()方法
from multiprocessing import Pipe, Process
import random def generate(pipe):
while True:
value = random.randrange(10)
pipe.send(value)
print("Value sent: %s" % (value)) def reader(pipe):
f = open("output.txt", "w")
while True:
value = pipe.recv()
f.write(str(value))
print(".") input_p, output_p = Pipe()
p1 = Process(target=generate, args=(input_p,))
p2 = Process(target=reader, args=(output_p,))
p1.start()
p2.start()
多进程也有事件Event,它们的工作方式与多线程类似,只是有一点需要记住,事件对象不能被传递到子进程的函数中,这样做会导致运行时错误,信号机制只能在主进程中被子进程共享:
from multiprocessing import Pool, Event
import time event = Event()
event.set() def worker(i):
if event.is_set():
time.sleep(0.1)
print("A - %s" % (time.time()))
event.clear()
else:
time.sleep(0.1)
print("B - %s" % (time.time()))
event.set() pool = Pool(3)
pool.map(worker, range(9))
Python之多线程与多进程(二)的更多相关文章
- Python之多线程和多进程
一.多线程 1.顺序执行单个线程,注意要顺序执行的话,需要用join. #coding=utf-8 from threading import Thread import time def my_co ...
- python的多线程和多进程(一)
在进入主题之前,我们先学习一下并发和并行的概念: --并发:在操作系统中,并发是指一个时间段中有几个程序都处于启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但任一时刻点上只有一个程序在处理 ...
- Python的多线程和多进程
(1)多线程的产生并不是因为发明了多核CPU甚至现在有多个CPU+多核的硬件,也不是因为多线程CPU运行效率比单线程高.单从CPU的运行效率上考虑,单任务进程及单线程效率是最高的,因为CPU没有任何进 ...
- Python【多线程与多进程】
import time,threading print("=======串行方式.并行两种方式调用run()函数=======")def run(): print('哈哈哈') # ...
- python的多线程、多进程代码示例
python多进程和多线程的区别:python的多线程不是真正意义上的多线程,由于python编译器的问题,导致python的多线程存在一个PIL锁,使得python的多线程的CPU利用率比预期的要低 ...
- selenium +python之多线程与多进程应用于自动化测试
多线程与多进程与自动化测试用例结合起来执行,从而节省测试用例的总体运行时间. 多线程执行测试测试用例 以百度搜索为例,通过不同的浏览器来启动不同的线程. from selenium import we ...
- Python之多线程与多进程(一)
多线程 多线程是程序在同样的上下文中同时运行多条线程的能力.这些线程共享同一个进程的资源,可以在并发模式(单核处理器)或并行模式(多核处理器)下执行多个任务 多线程有以下几个优点: 持续响应:在单线程 ...
- Python中多线程与多进程的恩恩怨怨
概念: 并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运 ...
- python的多线程、多进程、协程用代码详解
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
随机推荐
- Quartz.NET基础入门
Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调度作业.它实现了作业和 ...
- SQL函数TIMEDIFF在Java程序中使用报错的问题分析
需求背景 (读者可略过)司机每天从早到晚都会去到不同的自动售货机上补货,而且补货次数和路线等也是因人而异,补货依据是由系统优化并指派.但是目前系统还无法实施有效指挥和优良的补货策略,司机的补货活动因此 ...
- LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 .NET 4.5 installed Visual Studio 2012 Release Preview
Error 'LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt' after ...
- 【虚拟机-网络IP】虚拟机配置静态 IP 以后无法连接的解决办法
问题描述 将虚拟机内部 IP 地址从动态获取改成静态 IP 以后,远程连接失败. 问题分析 Azure 虚拟机的内部 IP 默认为动态分配, 由 DHCP 服务自动分配, 在虚拟机的生命周期内, 该 ...
- wpf ListBox删除选择项(支持多项)
搞了个ListBox删除选择项,开始老是不能把选择项删除干净,剩下几个.后来调试一下原来是ListBox在删除一个选择项之后立即更新,选择项也有变化.结果我想了个这样的方法来删除呵呵. Departm ...
- mysql-新增、更新、删除语句
1.插入数据: INSERT INTO t_book VALUES(NULL,'我爱我家',20,'张三',1); INSERT INTO t_book(id,bookName,price,autho ...
- width:100%与绝对定位同时存在,偏移出父级容器
当父级容器内的子元素width设为100%,而子元素又有绝对定位时,子元素伸展超出父级容器,像下面 出现这种情况的原因,width:100%,这个百分之百是相对其定位父级而言的,其定位父级有多宽,这个 ...
- 【Python图像特征的音乐序列生成】关于音乐生成的思路转变
在前几天的讨论会上,有师兄指出原来的方法实在是很难训练,所以我改进了音乐生成的思路. 首先,我用LSTM生成的一定是一段音乐的序列化表达,那么我就可以用成型的一些数据集去训练LSTM.为了避免生成的音 ...
- Android(java)学习笔记131:关于构造代码块,构造函数的一道面试题(华为面试题)
1. 代码实例: package text; public class TestStaticCon { public static int a = 0; static { a = 10; System ...
- UI与数据分离 与 UI的演进
解藕的好处:UI内部模块能够灵活的变化. MVC或者三层架构着重强调了数据.业务逻辑和UI的分离. (MVC中的C只是UI和业务逻辑模块间的一个中转组件,理论上应该是个轻模块.) 以前的关注的解藕技术 ...