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)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...
随机推荐
- ps应用
1.选中图层 ctrl+鼠标左键(win) command+鼠标左键(mac) 2.初始化 右侧:图层,历史记录,信息(面板选项-rgb,文档尺寸,像素),字符 编辑-首选项-单位与标尺-像素 窗口- ...
- 分拆素数和 HDU - 2098
把一个偶数拆成两个不同素数的和,有几种拆法呢? Input输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束.Output对应每个偶数,输出其拆成不同素数的个数,每个结果 ...
- 采用TCP协议实现PIC18F97J60 ethernet bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). TCP/IP Stac ...
- 关于int类型的赋值语句正确的有
A.char a=65; 对 B.int a=12.0; C.int a=12.0f; D.int a=(int)12.0 对
- 在 Visual Studio 中调试时映射调用堆栈上的方法
本文转自:https://msdn.microsoft.com/zh-cn/library/dn194476.aspx 1.创建代码图,以便在调试时对调用堆栈进行可视化跟踪. 你可以在图中进行标注以跟 ...
- Ubuntu实现wifi热点
系统:Ubuntu14.04 方法一: 打开网络连接,新建wifi,设置SSID和密码,完成设置后保存,再连接到隐藏的wifi,选择刚建立好的连接即可 优点:简单方便 缺点:建立的是Ad-hoc模式信 ...
- Set,List,Map,Vector,ArrayList的区别(转)
JAVA的容器---List,Map,Set Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtab ...
- CI框架(一)
CI工作流程: 所有的入口都从根目录下的index.php进入,确定应用所在目录后,加载 codeigniter/CodeIgniter.php 文件,该文件会顺序加载以下文件执行整个流 ...
- VMware 虚拟机桥接网络设置
一.桥接的基本原理 配置成桥接网络连接模式的虚拟机就当作主机所在以太网的一部分,虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑,可以像主机一样可以访问以太网中的所有共享资源和网络连 ...
- mat工具MemoryAnalyzer进行分析java内存溢出hprof文件
java服务端程序报错后会生成hprof文件,我们可以通过mat工具MemoryAnalyzer进行分析 下载地址: http://www.eclipse.org/mat/downloads.php ...