Python:进程
由于GIL的存在,python一个进程同时只能执行一个线程。因此在python开发时,计算密集型的程序常用多进程,IO密集型的使用多线程
1.多进程创建:
#创建方法1:将要执行的方法作为参数传给Process from multiprocessing import Process def f(name):
print 'hello',name if __name__ == '__main__': #需要注意的是,多进程只能在main中执行
p = Process(target=f,args=('pingy',)) #target=f指执行函数f,args=('pingy',)是指以元组方式传入函数的参数
p.start() #执行进程
p.join() #父进程停止,等待子进程执行完
#创建方法2:从Process继承,并重写run()
from multiprocessing import Process class MyProcess(Process):
def run(self):
print("MyProcess extended from Process") if __name__ == '__main__': #需要注意的是,多进程只能在main中执行
p2=MyProcess()
p2.start()
实例方法:
run(): #默认的run()函数调用target的函数,你也可以在子类中覆盖该函数
start() : #启动该进程
daemon(): #停止子进程,只执行父进程
join([timeout]) : #父进程被停止,直到子进程被执行完毕。当timeout为None时没有超时,否则有超时
is_alive(): #返回进程是否在运行。正在运行指启动后、终止前
terminate(): #结束进程
例:
from multiprocessing import Process
from threading import Thread
import time
import os def foo(n):
time.sleep(2)
print 'Number:',n
print '子进程ID:',os.getpid(),'父进程ID:',os.getpid() def main1():
for i in range(2):
foo(i) def main2():
for i in range(2):
p = Process(target=foo,args=(i,))
print p.name,'准备执行...' #p.name为进程名
p.start()
print p.pid,'开始执行...' #在进程start前,进程号p.pid为None
p.join(1) #join([timeout]) 父进程被停止,直到子进程被执行完毕。 if __name__ == '__main__':
print '主进程ID:',os.getpid()
print '++++++++++++++++++++++++++++++++++++++++++'
main1()
print '------------------------------------------'
main2()
输出结果:
主进程ID: 84792
++++++++++++++++++++++++++++++++++++++++++
Number: 0
子进程ID: 84792 父进程ID: 84792
Number: 1
子进程ID: 84792 父进程ID: 84792
------------------------------------------
Process-1 准备执行...
123316 开始执行...
Process-2 准备执行...
85716 开始执行...
Number: 0
子进程ID: 123316 父进程ID: 123316
Number: 1
子进程ID: 85716 父进程ID: 85716
设置daemon属性:
#不加daemon: import multiprocessing
import time def worker(interval):
print("work start:{0}".format(time.ctime()));
time.sleep(interval)
print("work end:{0}".format(time.ctime())); if __name__ == "__main__":
p = multiprocessing.Process(target = worker, args = (3,))
p.start()
print "end!"
执行结果:
end!
work start:Thu Oct 20 16:46:12 2016
work end:Thu Oct 20 16:46:15 2016
#加上daemon后: import multiprocessing
import time def worker(interval):
print("work start:{0}".format(time.ctime()));
time.sleep(interval)
print("work end:{0}".format(time.ctime())); if __name__ == "__main__":
p = multiprocessing.Process(target = worker, args = (3,))
p.daemon = True
p.start()
print "end!"
输出结果:
end!
设置daemon执行完结束的方法:
import multiprocessing
import time def worker(interval):
print("work start:{0}".format(time.ctime()));
time.sleep(interval)
print("work end:{0}".format(time.ctime())); if __name__ == "__main__":
p = multiprocessing.Process(target = worker, args = (3,))
p.daemon = True
p.start()
p.join() #
print "end!"
输出结果:
work start:Thu Oct 20 16:49:34 2016
work end:Thu Oct 20 16:49:37 2016
end!
将进程定义为类:
import multiprocessing
import time class ClockProcess(multiprocessing.Process):
def __init__(self, interval):
multiprocessing.Process.__init__(self)
self.interval = interval def run(self):
n = 5
while n > 0:
print("the time is {0}".format(time.ctime()))
time.sleep(self.interval)
n -= 1 if __name__ == '__main__':
p = ClockProcess(3)
p.start()
输出结果:
the time is Thu Oct 20 16:42:21 2016
the time is Thu Oct 20 16:42:24 2016
the time is Thu Oct 20 16:42:27 2016
the time is Thu Oct 20 16:42:30 2016
the time is Thu Oct 20 16:42:33 2016
多进程与多线程的区别:
from multiprocessing import Process
import threading
import time
li = []
def run(li1,n):
li1.append(n)
print li1 if __name__ == '__main__':for i in range(10): #创建多进程,每个进程占用单独内存
p = Process(target=run,args=[li,i])
p.start()
time.sleep(1) print '我是分割线'.center(50,'*') for i in range(10): #创建多线程,所有线程共享内存
t = threading.Thread(target=run,args=[li,i])
t.start()
执行结果:
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
*****************我是分割线******************
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2[, 03, , 14, , 25, ]3
, 4, 5]
[0, 1, 2[, 03, , 14, , 25, , 36, , 47, ][5
0, , 61, , 72, , 83],
4, 5, 6, [70, , 81, , 92],
3, 4, 5, 6, 7, 8, 9]
2.多进程之间资源共享方法
(1)锁:作用是当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突。它又分为Lock和rLock,rLock中除了状态locked和unlocked外还记录了当前lock的owner和递归层数,使得RLock可以被同一个线程多次acquire()。如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
#锁的使用方法:
import multiprocessing
lock = multiprocessing.Lock() #Lock对象
lock.acquire(([timeout])) #锁定。timeout为可选项,如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁
lock.release() #解锁 rLock = multiprocessing.RLock() #RLock对象
rLock.acquire(([timeout])) #锁定。timeout为可选项,如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁
rLock.release() #解锁
例:
import multiprocessing
import sys def worker_with(lock, f):
with lock:
fs = open(f, 'a+')
n = 10
while n > 1:
fs.write("Lockd acquired via with\n")
n -= 1
fs.close() def worker_no_with(lock, f):
lock.acquire()
try:
fs = open(f, 'a+')
n = 10
while n > 1:
fs.write("Lock acquired directly\n")
n -= 1
fs.close()
finally:
lock.release() if __name__ == "__main__":
lock = multiprocessing.Lock()
f = "file.txt"
w = multiprocessing.Process(target = worker_with, args=(lock, f))
nw = multiprocessing.Process(target = worker_no_with, args=(lock, f))
w.start()
nw.start()
print "end"
输出结果:
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lockd acquired via with
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
Lock acquired directly
(2)multiprocess.Queue:实现进/线程间的同步
- FIFO(先进先出)队列
- LIFO(后进先出)队列
- PriorityQueue(优先级)队列
注意:Queue.Queue是进程内非阻塞队列,multiprocess.Queue是跨进程通信队列。多进程前者是各自私有,后者是各子进程共有。
实例方法:
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
FIFO(先进先出)队列:
import Queue q = Queue.Queue() for i in range(5):
q.put(i) while not q.empty():
print q.get()
输出结果: 0
1
2
3
4
LIFO后进先出队列:
import Queue q = Queue.LifoQueue() for i in range(5):
q.put(i) while not q.empty():
print q.get()
输出结果: 4
3
2
1
优先级队列:
import Queue
import threading
import time exitFlag = 0 class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print "Starting " + self.name
process_data(self.name, self.q)
print "Exiting " + self.name def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s processing %s" % (threadName, data)
else:
queueLock.release()
time.sleep(1) threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1 # 创建新线程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1 # 填充队列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release() # 等待队列清空
while not workQueue.empty():
pass # 通知线程是时候退出
exitFlag = 1 # 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
输出结果:
Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-1 processing One
Thread-2 processing Two
Thread-3 processing Three
Thread-1 processing Four
Thread-2 processing Five
Exiting Thread-3
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread
multiprocess.Queue:实现进程间的同步:
例1:
from multiprocessing import Process,Queue
def foo(q,n):
q.put(n) if __name__ == '__main__':
que=Queue()
for i in range(5):
p=Process(target=foo,args=(que,i))
p.start()
p.join() print(que.qsize())
输出结果:
5
例2:
import multiprocessing def writer_proc(q):
try:
q.put(1, block = False)
except:
pass def reader_proc(q):
try:
print q.get(block = False)
except:
pass if __name__ == "__main__":
q = multiprocessing.Queue()
writer = multiprocessing.Process(target=writer_proc, args=(q,))
writer.start() reader = multiprocessing.Process(target=reader_proc, args=(q,))
reader.start()
输出结果:
1
(3)multiprocessing.Value与multiprocessing.Array:进行数据共享
from multiprocessing import Process,Value,Array def foo1(n,a):
n.value = 3
for i in range(len(a)):
a[i] = -a[i] if __name__ == '__main__':
num = Value('d',0.0) #d的意思是小数.创建0.0
arr = Array('i',range(10)) #i的意思是整数.创建一个0-9的整数
p = Process(target=foo1,args=(num,arr))
p.start()
p.join()
print num.value
print arr[:]
输出结果:
3.0
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
(4)multiprocessing.Manager:数据共享
from multiprocessing import Manager,Process def f(d,l):
d[1] = ''
d[''] = 2
d[0.25] = None
l.reverse()
if __name__ == '__main__':
manage = Manager()
d = manage.dict() #创建一个进程间可共享的dict
l = manage.list(range(10)) #创建一个进程间可共享的list
p = Process(target=f,args=(d,l))
p.start()
p.join()
print d
print l
输出结果:
{0.25: None, 1: '', '': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
3.pool:如果需要多个子进程时可以考虑使用进程池(pool)来管理
Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
(1)使用进程池(非阻塞)
#使用进程池(非阻塞)
import time
import multiprocessing def fun(msg):
print 'MSG:',msg
time.sleep(3)
print 'end'
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=3)
for i in xrange(4):
msg = 'hello,%d' %(i)
pool.apply_async(fun,(msg,)) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
print '-----------------------'
pool.close()
pool.join()
print 'Sub-processes done'
输出结果:
-----------------------
MSG: hello,0
MSG: hello,1
MSG: hello,2
end
MSG: hello,3
end
end
end
Sub-processes done
(2)使用进程池(阻塞)
import time,multiprocessing def fun(msg):
print 'MSG:',msg
time.sleep(3)
print 'end'
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=3)
for i in xrange(4):
msg = 'hello,%d' %i
pool.apply(fun,(msg,))
print '-------------------------------'
pool.close()
pool.join()
print 'Sub-processes done'
输出结果:
MSG: hello,0
end
MSG: hello,1
end
MSG: hello,2
end
MSG: hello,3
end
-------------------------------
Sub-processes done
4.Pipe:用于具有亲缘关系进程间的通信,有名的管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
实现机制:
管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。
import multiprocessing
import time def proc1(pipe):
while True:
for i in range(10000):
print 'send:%s' %i
pipe.send(i)
time.sleep(1) def proc2(pipe):
while True:
print 'proc2 recv:',pipe.recv()
time.sleep(1) def proc3(pipe):
while True:
print 'proc3 recv:',pipe.recv()
time.sleep(1) if __name__ == '__main__':
pipe = multiprocessing.Pipe()
p1 = multiprocessing.Process(target=proc1,args=(pipe[0],))
p2 = multiprocessing.Process(target=proc2, args=(pipe[1],))
#p3 = multiprocessing.Process(target=proc3, args=(pipe[1],))
p1.start()
p2.start()
#p3.start()
p1.join()
p2.join()
#p3.join()
输出结果:
send:0
proc2 recv: 0
send:1
proc2 recv: 1
send:2
proc2 recv: 2
send:3
proc2 recv: 3
send:4
proc2 recv: 4
send:5
proc2 recv: 5
send:6
proc2 recv: 6
Python:进程的更多相关文章
- python——进程基础
我们现在都知道python的多线程是个坑了,那么多进程在这个时候就变得很必要了.多进程实现了多CPU的利用,效率简直棒棒哒~~~ 拥有一个多进程程序: #!/usr/bin/env python #- ...
- 使用gdb调试Python进程
使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...
- python进程、线程、协程(转载)
python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...
- Python进程、线程、协程详解
进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...
- python进程池剖析(一)
python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序.如果需要 ...
- python——进程、线程、协程
Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...
- python/进程线程的总结
python/进程线程的总结 一.进程和线程的描述: 进程:最小的资源管理单位 线程:最小的执行单位 执行一个进程时就默认执行一个线程(主线程) 进程和线程的工作方式: 串行: 假如共有A.B.C任务 ...
- python 进程介绍 进程简单使用 join 验证空间隔离
一.多道程序设计技术(详情参考:https://www.cnblogs.com/clschao/articles/9613464.html) 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行 ...
- Python 进程之间共享数据
最近遇到多进程共享数据的问题,到网上查了有几篇博客写的蛮好的,记录下来方便以后查看. 一.Python multiprocessing 跨进程对象共享 在mp库当中,跨进程对象共享有三种方式,第一种 ...
- python进程、多进程
进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...
随机推荐
- MFC 单文档消息执行顺序。
theApp构造, InitInstance void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO* lpMMI) BOOL CMyFrameWnd::OnNcCr ...
- AChartEngine 图表绘制
AChartEngine Android 平台的图表开发库, 能绘制 折线图, 饼图, 气泡图, 柱状图, 散点图, 面积图等统计图表. 这些我记录一下,柱状图.折线图和饼状图的小例子.有兴趣的朋友, ...
- KETTLE实现数据的删除和更新
一.实现目标 源数据库的数据更新或者删除之后,目标数据库的数据跟着更新或删除,整体流程截图如下: 一.准备工作 源数据库ORACLE 目标数据库MongoDB,在源数据库添加删除.更新触发器 二.操 ...
- LVS+keepalived负载均衡实战
1 首先安装虚拟机 安装系统 这里 配置两台虚拟机 1:192.168.137.102 2:192.168.137.103 分别安装tomcat 默认80端口,同时都是开启状态 配置192.168 ...
- MongoDB(七)MongoDb数据结构
首先,向数据库插入一条bjson数据 首先是定义文档,然后使用admin用户名密码登录,进入test数据库,向test数据库中插入此文档("表名称和表中的记录") 插入结果,查看m ...
- C语言隐形密码输入
今天费了老大的劲,终于做出来了!虽然简单,但也是自己的心血,分享一下! #include<stdio.h> #include<conio.h> int main(){ char ...
- tracert与pathping
trace route(windows命令为tracert,Linux命令为traceroute)命令可以列出本地计算机与目标计算机之间所有经过的计算机信息.可以输入目标计算机的名字(如www.bai ...
- yii + elasticsearch 手册
https://zhuowenji1.gitbooks.io/elasticsearch/content/an_zhuang_yii2.html
- jsp页面无法解析EL表达式
从eclipse迁移到idea,真是各种被坑. 今天遇到的jsp无法解析EL,页面直接就显示${xxx}好坑爹 Root cause:idea生成的web.xml 的web-app版本居然是2.3,2 ...
- cxf client端借口类型找不到问题
问题: log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.Exception in ...