由于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:进程的更多相关文章

  1. python——进程基础

    我们现在都知道python的多线程是个坑了,那么多进程在这个时候就变得很必要了.多进程实现了多CPU的利用,效率简直棒棒哒~~~ 拥有一个多进程程序: #!/usr/bin/env python #- ...

  2. 使用gdb调试Python进程

    使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...

  3. python进程、线程、协程(转载)

    python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...

  4. Python进程、线程、协程详解

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...

  5. python进程池剖析(一)

    python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序.如果需要 ...

  6. python——进程、线程、协程

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...

  7. python/进程线程的总结

    python/进程线程的总结 一.进程和线程的描述: 进程:最小的资源管理单位 线程:最小的执行单位 执行一个进程时就默认执行一个线程(主线程) 进程和线程的工作方式: 串行: 假如共有A.B.C任务 ...

  8. python 进程介绍 进程简单使用 join 验证空间隔离

    一.多道程序设计技术(详情参考:https://www.cnblogs.com/clschao/articles/9613464.html) 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行 ...

  9. Python 进程之间共享数据

    最近遇到多进程共享数据的问题,到网上查了有几篇博客写的蛮好的,记录下来方便以后查看. 一.Python multiprocessing 跨进程对象共享  在mp库当中,跨进程对象共享有三种方式,第一种 ...

  10. python进程、多进程

    进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...

随机推荐

  1. 自己用C语言写单片机PIC16 serial bootloader

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 为什么自己写bootl ...

  2. prototype数组方法的实现

    数组插入元素push Array.prototype.push=function(){ for(var i=0;i<arguments.length;i++){ this[this.length ...

  3. Welcome to China

    subway, railway, highway ,way way to dieofficer,announcer, professor, sir sir to lieWelcome to China

  4. DEM数据如何生成高程点

    这次给大家介绍一个arcgis里的实用功能:通过地形数据提取高程点. 首先做好准备工作: 1.地形数据下载获取 2.软件准备 locaspace viewer:http://rj.baidu.com/ ...

  5. 装饰模式(Decorator pattern)

    装饰模式(Decorator pattern): 又名包装模式(Wrapper pattern), 它以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式以对客户透明的方式动态的给 ...

  6. 《SSM框架搭建》一.构建maven web项目

    一.创建maven工程File-New-other-Maven Project 二.设置项目工作空间,取消默认勾选,手动设置 三.选择internal,输入web,选择maven.archetypes ...

  7. Mac升级到Yosemite后默认的php版本不支持imagetfftext函数问题解决

    Mac升级到yosemite后,php也自动升级,运行项目的时候发现后台验证码显示不出来.调试一下发现imagetfftext这个函数不存在,应该gd没有安装完全,因为Mac上的php实现系统自带的, ...

  8. 删除注释云平台JS,加快DISCUZ访问

      对于港台或者美国服务器的用户可能感觉访问慢,页面卡:实际上是由于 http://www.discuzlab.com/discuz.gtimg.cn/cloud/scripts/discuz_tip ...

  9. Java画图程序设计

    本文讲述一个画图板应用程序的设计,屏幕抓图如下: 『IShape』 这是所有图形类(此后称作模型类)都应该实现接口,外部的控制类,比如画图板类就通过这个接口跟模型类“交流”.名字开头的I表示它是一个接 ...

  10. BZOJ2038: [2009国家集训队]小Z的袜子(hose)

    Time Limit: 20 Sec  Memory Limit: 259 MB Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天, ...