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学习资料的小伙伴可以加点击下方链 ...
随机推荐
- JavaScript中的小陷阱(不定期更新。。)
1. var scores = [1, 2, 3]; var total = 0; for (var score in scores) { total += score; } var mean = t ...
- fleet-运行一个全局的单元
运行一个全局的单元 正如前面所提到的,全局单元是有用的,用于在您的集群中的所有机器上运行一个单元.它不会比一个普通的单元差太多,而是一个新的x-fleet参数称为Global=true.这是一个示例单 ...
- idea远程debug:tomcat
在tomcat的bin/startup.sh中添加: 27780debug的端口 declare -x CATALINA_OPTS="-server -Xdebug -Xnoagent -D ...
- ServletContext--HttpServletResponse--web项目执行流程
一.ServletContext 接口(javax.servlet) 定义:public interface ServletContext 原理: Tomcat启动的时候,需要识别webapp ...
- 初识AutoCompleteTextView
AutoCompleteTextView自动补全框继承自TextView和EditView,通过一个下拉框的形式可以补全信息. 可以通过setThreshold()方法指定用户输入多少个字符后开始显示 ...
- ORA-02273: this unique/primary key is referenced by some foreign keys
关于ORA-02273错误,以前还真没有仔细留意过.昨天遇到了这个问题,遂顺便总结一番,以后遇到这类问题就可以直接用下面方案解决.如下所示,我们首先准备一下测试环境. CREATE TABLE TES ...
- TC和脚本语言
TC:Turbo C 集成开发环境是由Borland 公司开发的一套C 语言开发工具,它集成了程序编辑.调试.链接等多种功能.在DOS 系统时代,Turbo C 是被最广泛使用的一种PC 机应用程序开 ...
- 全站变灰的CSS代码-适合特殊时刻哀悼
将下面CSS代码应用到HTML标签或者是BODY标签 filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.o ...
- BZOJ 2851: 极限满月 虚树 or 树链的并
2851: 极限满月 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 170 Solved: 82[Submit][Status][Discuss] ...
- Zero to One书摘
之所以叫书摘,是因为翻译不像翻译,书评不像书评,更像是把觉得有意义的部分摘抄下来. 第一章,未来的挑战 如何定义未来? 大部分人定义的未来都只是现在的简单延伸而已,其实技术的改变是人们无法预料的. ...