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)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...
随机推荐
- Python之MySQL操作及Paramiko模块操作
一.MySQL简介 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQ ...
- 【Python】pymongo使用
官方文档:http://api.mongodb.com/python/current/index.html MongoReplicaSetClient:http://api.mongodb.com/p ...
- PHP中获取当前页面的完整URL
//获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br>"; #localhost//获取网页地址 echo $_SERVER['PHP ...
- 采用UDP协议的PIC32MZ ethernet bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 经过千辛万苦,今天终于 ...
- Leetcode5:Longest Palindromic Substring@Python
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 9、SQL Server 操作数据
插入数据 使用Insert Into 插入 if(exists(select * from sys.databases where name = 'webDB')) drop database web ...
- 微软第四题 给定cost能遍历的最大城市数
有向图中N*N矩阵 cost:M, 最多可以遍历的结点个数 例如A可以有0->1->2->0->1 代价:2+2+3+2=9<10 输出4 #include <io ...
- Javascript 中 == 和 === 区别
转载几张图片,说明其中的具体意义 这是 == 这是 === 完整比较图: 红色:=== 橙色:== 黄色:<= 和 >= 同时成立,== 不成立 蓝色:只有 >= 绿色:只有 < ...
- 移动端touch事件影响click事件以及在touchmove添加preventDefault导致页面无法滚动的解决方法
这两天自己在写一个手机网页,用到了触屏滑动的特效,就是往右滑动的时候左侧隐藏的菜单从左边划出来. 做完之后在手机原生浏览器中运行正常,但在QQ和微信中打开,发现touchmove只会触发一次,而且to ...
- 使用JDBC访问SQLServer 2008
使用JDBC访问SQLServer 2008 // 准备数据库驱动程序 String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriv ...