Python进阶(4)_进程与线程 (python并发编程之多进程)
一、python并发编程之多进程
1.1 multiprocessing模块介绍
由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。
该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
  group: 线程组,目前还没有实现,库引用中提示必须是None; 
  target: 要执行的方法; 
  name: 进程名; 
  args/kwargs: 要传入方法的参数。
实例方法:
is_alive():返回进程是否在运行。
join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
start():进程准备就绪,等待CPU调度
run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
terminate():不管任务是否完成,立即停止工作进程
属性:
daemon:和线程的setDeamon功能一样
name:进程名字。
pid:进程号。
方法介绍:
p1=Process(target=foo,args=('p1',))    开启子进程
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
在linux中,主进程的全局变量,子进程能用
在window中,主进程的全局变量,子进程不能用能用
1.2 创建并开启子进程的两种方式
通过函数:
#函数方式
def foo(name):
print('%s starting'%name)
time.sleep(random.randrange(1,5))
print('%s is end'%name) if __name__ == '__main__':
print('主进程starting') p1=Process(target=foo,args=('p1',))
p2=Process(target=foo,args=('p2',))
p3=Process(target=foo,args=('p3',)) # p1.daemon = True
# p2.daemon = True
# p3.daemon = True p1.start()
p2.start()
p3.start() # p1.join()
# p2.join()
# p3.join() # time.sleep(1)
print('主进程ending')
通过类的方式:
#用类的方式创建子进程
class MyProcess(Process):
def __init__(self,name):
super().__init__()
# self.name=name def run(self):
print('%s starting' % self.name)
time.sleep(random.randrange(1, 5))
print('%s id is %s' % (self.name,self.pid))
print('%s is end'%self.name) if __name__ == '__main__':
print('主进程starting')
for i in range(4):
p = MyProcess(str(i))
p.start() print('主进程ending')
1.3 Process对象的其他方法或属性
#进程对象的其他方法一:terminate,is_alive
from multiprocessing import Process
import time
import random class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__() def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randrange(,))
print('%s is piao end' %self.name) p1=Piao('egon1')
p1.start() p1.terminate()#关闭进程,不会立即关闭,所以is_alive立刻查看的结果可能还是存活
print(p1.is_alive()) #结果为True print('开始')
print(p1.is_alive()) #结果为False
进程对象的其他方法一:terminate,is_alive
#进程对象的其他方法二:p.daemon=True,p.join
from multiprocessing import Process
import time
import random class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__()
def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randrange(,))
print('%s is piao end' %self.name) p=Piao('egon')
p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程死,p跟着一起死
p.start()
p.join(0.0001) #等待p停止,等0.0001秒就不再等了
print('开始')
#进程对象的其他方法二:p.daemon=True,p.join
注:p.join(),是父进程在等p的结束,是父进程阻塞在原地,而p仍然在后台运行
#进程对象的其他属性:name,pid
from multiprocessing import Process
import time
import random
class Piao(Process):
def __init__(self,name):
# self.name=name
# super().__init__() #Process的__init__方法会执行self.name=Piao-,
# #所以加到这里,会覆盖我们的self.name=name #为我们开启的进程设置名字的做法
super().__init__()
self.name=name def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randrange(,))
print('%s is piao end' %self.name) p=Piao('egon')
p.start()
print('开始')
print(p.pid) #查看pid
#进程对象的其他属性:name,pid
1.2 进程间通讯
1.2.1进程间通信(IPC)方式一:队列(推荐使用)
from multiprocessing import Process
import queue def f(q,n):
q.put(n*n+1)
print("son process",id(q)) if __name__ == '__main__': q = queue.Queue()
print("main process",id(q)) for i in range(3):
p = Process(target=f, args=(q,i))
p.start() print(q.get())
print(q.get())
print(q.get())
1.2.2进程间通信(IPC)方式二:管道(不推荐使用,了解即可)
from multiprocessing import Pipe,Process def foo(sk):
sk.send("hello world")
print(sk.recv()) if __name__ == '__main__':
sock, conn = Pipe()
p=Process(target=foo,args=(sock,))
p.start() print(conn.recv())
conn.send("hi son") >>:hello world
hi son
Pipe()返回的两个连接对象代表管道的两端。 每个连接对象都有send()和recv()方法(等等)。 请注意,如果两个进程(或线程)尝试同时读取或写入管道的同一端,管道中的数据可能会损坏。
1.2.3进程间通信方式三:共享数据(不推荐使用,了解即可)
Queue和pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。可以通过Manager实现数据共享,
从数据安全角度看,进程间通信应该尽量避免使用本节所讲的共享数据的方式
用manager实现进程共享数据
from multiprocessing import Process,Manager def foo(d,l,i):
d[i] = i
d['egon'] = 'egon'
l.append(i**2) if __name__ == '__main__':
# manager = Manager()
dic = Manager().dict()
Mlist = Manager().list([11,22,33])
l=[]
for i in range(5):
p=Process(target=foo,args=(dic,Mlist,i))
p.start()
l.append(p) for j in l:
j.join() print(dic)
print(Mlist)
1.3 进程池(重点学习)
开多进程的目的是为了并发,如果有多核,通常有几个核就开几个进程,进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行),但很明显需要并发执行的任务要远大于核数,这时我们就可以通过维护一个进程池来控制进程数目,比如httpd的进程模式,规定最小进程数和最大进程数...
进程池(Pool)可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,就重用进程池中的进程。
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。
进程池实例:
from multiprocessing import Pool
import time def foo(n):
print(n)
time.sleep(1) if __name__ == '__main__': pool_obj=Pool(5) for i in range(100):
pool_obj.apply_async(func=foo,args=(i,)) pool_obj.close()
pool_obj.join() print("ending")
Python进阶(4)_进程与线程 (python并发编程之多进程)的更多相关文章
- Python全栈【进程、线程】
		
Python全栈[进程.线程] 本节内容: 进程 线程 协程 I/O多路复用 进程 1.进程就是一个程序在一个数据集上的一次动态执行过程,进程是资源分配的最小单元. 2.进程一般由程序.数据集.进程控 ...
 - Python学习之GIL&进程池/线程池
		
8.6 GIL锁** Global interpreter Lock 全局解释器锁 实际就是一把解释器级的互斥锁 In CPython, the global interpreter lock, or ...
 - Python语法速查: 20. 线程与并发
		
返回目录 本篇索引 (1)线程基本概念 (2)threading模块 (3)线程间同步原语资源 (4)queue (1)线程基本概念 当应用程序需要并发执行多个任务时,可以使用线程.多个线程(thre ...
 - python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
		
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
 - 百万年薪python之路  --  并发编程之  多进程 一
		
并发编程之 多进程 一. multiprocessing模块介绍  python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...
 - Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
		
1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...
 - Python进阶(2)_进程与线程的概念
		
1 进程与线程相关概念 1.1 进程 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成,是最小的资源管理单元 程序:用来描述进程要完成哪些功能 ...
 - python 学习笔记八 进程和线程 (进阶篇)
		
什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执 ...
 - Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速
		
Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...
 
随机推荐
- ssh-keygen配合ssh_config免密码登录VPS
			
ssh-keygen配合ssh_config免密码登录VPS Posted by fiture / 2012年12月29日 / 「Ubuntu」「分享」 用过终端登录远程服务器或者VPS的童鞋都用过类 ...
 - 键值对集合 dict(字典)
			
xx= { ss, ss } 创建字典 len(ss) 返回字典到长度,len函数可以返回任何集合的长度,list.tuple.dict都是集合的一种 什么是dict 我们已经知道,list 和 tu ...
 - Vue 组件 非父子组件通信
			
有时候两个组件也需要通信(非父子关系),在简单的场景下,可以使用一个空的vue实例作为中央事件总线: var bus = new Vue(); //触发组件a中的事件 bus.$emit('id-se ...
 - eclipse 建立maven项目 显示红叉的解决方法
			
1.建立好之后就会发现项目有红叉. 这时发现查查在main处,打开项目>属性>Java Build Path>source,发现里边有红叉(如下图),这是由于我们的src/main下 ...
 - 基于GitLab的前端Assets发布体系
			
以SVN+RMS为核心的发布系统,对前端开发的影响上来看,存在以下问题: 覆盖式的发布,容易导致线上问题. js一旦发布,就有可能被任意其他页面使用.被引用的越多,就越重要.一旦核心js出现故障,影响 ...
 - mybatis like用法
			
针对不同的数据库,like的用法是不一样的,现在具体来说一下 1,SQL SERVER SELECT * FROM user WHERE name like '%'+#{name}+'%' 2,Ora ...
 - 第一百八十四节,jQuery-UI,验证注册表单
			
jQuery-UI,验证注册表单 html <form id="reg" action="123.html" title="会员注册" ...
 - 嵌入式开发之davinci--- 8148/8168/8127 中的音频alsa 采集
			
1.snd_pcm_open,打开句柄. 2.配置参数,可能用到的接口:snd_pcm_hw_params_alloca.snd_pcm_hw_params_any.snd_pcm_hw_params ...
 - HDU 3080 The plan of city rebuild(除点最小生成树)
			
题意 一个城市原来有l个村庄 e1条道路 又添加了n个村庄 e2条道路 后来后销毁了m个村庄 与m相连的道路也销毁了 求使全部未销毁村庄相互连通最小花费 不能连通输出what a pity ...
 - Unity官方发布热更新方案性能对照
			
孙广东 2016.3.11 Unity应用的iOS热更新 作者:丁治宇 Unity TechnologiesChina Agenda • 什么是热更新 • 为何要热更新 • 怎样在iOS 上对 ...