由于GIL的存在,python一个进程同时只能执行一个线程。因此在python开发时,计算密集型的程序常用多进程,IO密集型的使用多线程

1.多进程创建:

  1. #创建方法1:将要执行的方法作为参数传给Process
  2.  
  3. from multiprocessing import Process
  4.  
  5. def f(name):
  6. print 'hello',name
  7.  
  8. if __name__ == '__main__': #需要注意的是,多进程只能在main中执行
  9.   p = Process(target=f,args=('pingy',)) #target=f指执行函数f,args=('pingy',)是指以元组方式传入函数的参数
  10.   p.start() #执行进程
  11.   p.join() #父进程停止,等待子进程执行完
  1. #创建方法2:从Process继承,并重写run()
  2. from multiprocessing import Process
  3.  
  4. class MyProcess(Process):
  5. def run(self):
  6. print("MyProcess extended from Process")
  7.  
  8. if __name__ == '__main__': #需要注意的是,多进程只能在main中执行
  9. p2=MyProcess()
  10. p2.start()

 实例方法:

  1. run(): #默认的run()函数调用target的函数,你也可以在子类中覆盖该函数
  2. start() #启动该进程
  3. daemon(): #停止子进程,只执行父进程
  4. join([timeout]) #父进程被停止,直到子进程被执行完毕。当timeout为None时没有超时,否则有超时
  5. is_alive(): #返回进程是否在运行。正在运行指启动后、终止前
  6. terminate(): #结束进程

例:

  1. from multiprocessing import Process
  2. from threading import Thread
  3. import time
  4. import os
  5.  
  6. def foo(n):
  7. time.sleep(2)
  8. print 'Number:',n
  9. print '子进程ID:',os.getpid(),'父进程ID:',os.getpid()
  10.  
  11. def main1():
  12. for i in range(2):
  13. foo(i)
  14.  
  15. def main2():
  16. for i in range(2):
  17. p = Process(target=foo,args=(i,))
  18. print p.name,'准备执行...' #p.name为进程名
  19. p.start()
  20. print p.pid,'开始执行...' #在进程start前,进程号p.pid为None
  21. p.join(1) #join([timeout]) 父进程被停止,直到子进程被执行完毕。
  22.  
  23. if __name__ == '__main__':
  24. print '主进程ID:',os.getpid()
  25. print '++++++++++++++++++++++++++++++++++++++++++'
  26. main1()
  27. print '------------------------------------------'
  28. main2()

输出结果:

  1. 主进程ID: 84792
  2. ++++++++++++++++++++++++++++++++++++++++++
  3. Number: 0
  4. 子进程ID: 84792 父进程ID: 84792
  5. Number: 1
  6. 子进程ID: 84792 父进程ID: 84792
  7. ------------------------------------------
  8. Process-1 准备执行...
  9. 123316 开始执行...
  10. Process-2 准备执行...
  11. 85716 开始执行...
  12. Number: 0
  13. 子进程ID: 123316 父进程ID: 123316
  14. Number: 1
  15. 子进程ID: 85716 父进程ID: 85716

设置daemon属性:

  1. #不加daemon:
  2.  
  3. import multiprocessing
  4. import time
  5.  
  6. def worker(interval):
  7. print("work start:{0}".format(time.ctime()));
  8. time.sleep(interval)
  9. print("work end:{0}".format(time.ctime()));
  10.  
  11. if __name__ == "__main__":
  12. p = multiprocessing.Process(target = worker, args = (3,))
  13. p.start()
  14. print "end!"

执行结果:

  1. end!
  2. work start:Thu Oct 20 16:46:12 2016
  3. work end:Thu Oct 20 16:46:15 2016
  1. #加上daemon后:
  2.  
  3. import multiprocessing
  4. import time
  5.  
  6. def worker(interval):
  7. print("work start:{0}".format(time.ctime()));
  8. time.sleep(interval)
  9. print("work end:{0}".format(time.ctime()));
  10.  
  11. if __name__ == "__main__":
  12. p = multiprocessing.Process(target = worker, args = (3,))
  13. p.daemon = True
  14. p.start()
  15. print "end!"

输出结果:

  1. end

设置daemon执行完结束的方法:

  1. import multiprocessing
  2. import time
  3.  
  4. def worker(interval):
  5. print("work start:{0}".format(time.ctime()));
  6. time.sleep(interval)
  7. print("work end:{0}".format(time.ctime()));
  8.  
  9. if __name__ == "__main__":
  10. p = multiprocessing.Process(target = worker, args = (3,))
  11. p.daemon = True
  12. p.start()
  13. p.join() #
  14. print "end!"

输出结果:

  1. work start:Thu Oct 20 16:49:34 2016
  2. work end:Thu Oct 20 16:49:37 2016
  3. end!

将进程定义为类:

  1. import multiprocessing
  2. import time
  3.  
  4. class ClockProcess(multiprocessing.Process):
  5. def __init__(self, interval):
  6. multiprocessing.Process.__init__(self)
  7. self.interval = interval
  8.  
  9. def run(self):
  10. n = 5
  11. while n > 0:
  12. print("the time is {0}".format(time.ctime()))
  13. time.sleep(self.interval)
  14. n -= 1
  15.  
  16. if __name__ == '__main__':
  17. p = ClockProcess(3)
  18. p.start()

输出结果:

  1. the time is Thu Oct 20 16:42:21 2016
  2. the time is Thu Oct 20 16:42:24 2016
  3. the time is Thu Oct 20 16:42:27 2016
  4. the time is Thu Oct 20 16:42:30 2016
  5. the time is Thu Oct 20 16:42:33 2016

多进程与多线程的区别:

  1. from multiprocessing import Process
  2. import threading
  3. import time

  4. li = []
  5. def run(li1,n):
  6. li1.append(n)
  7. print li1
  8.  
  9. if __name__ == '__main__':for i in range(10): #创建多进程,每个进程占用单独内存
  10. p = Process(target=run,args=[li,i])
  11. p.start()
  12. time.sleep(1)
  13.  
  14. print '我是分割线'.center(50,'*')
  15.  
  16. for i in range(10): #创建多线程,所有线程共享内存
  17. t = threading.Thread(target=run,args=[li,i])
  18. t.start()

执行结果:

  1. [0]
  2. [1]
  3. [2]
  4. [3]
  5. [4]
  6. [5]
  7. [6]
  8. [7]
  9. [8]
  10. [9]
  11. *****************我是分割线******************
  12. [0]
  13. [0, 1]
  14. [0, 1, 2]
  15. [0, 1, 2, 3]
  16. [0, 1, 2[, 03, , 14, , 25, ]3
  17. , 4, 5]
  18. [0, 1, 2[, 03, , 14, , 25, , 36, , 47, ][5
  19. 0, , 61, , 72, , 83],
  20. 4, 5, 6, [70, , 81, , 92],
  21. 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才能真正释放所占用的琐。

  1. #锁的使用方法:
  2. import multiprocessing
  3. lock = multiprocessing.Lock() #Lock对象
  4. lock.acquire(([timeout])) #锁定。timeout为可选项,如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁
  5. lock.release() #解锁
  6.  
  7. rLock = multiprocessing.RLock() #RLock对象
  8. rLock.acquire(([timeout])) #锁定。timeout为可选项,如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁
  9. rLock.release() #解锁

例:

  1. import multiprocessing
  2. import sys
  3.  
  4. def worker_with(lock, f):
  5. with lock:
  6. fs = open(f, 'a+')
  7. n = 10
  8. while n > 1:
  9. fs.write("Lockd acquired via with\n")
  10. n -= 1
  11. fs.close()
  12.  
  13. def worker_no_with(lock, f):
  14. lock.acquire()
  15. try:
  16. fs = open(f, 'a+')
  17. n = 10
  18. while n > 1:
  19. fs.write("Lock acquired directly\n")
  20. n -= 1
  21. fs.close()
  22. finally:
  23. lock.release()
  24.  
  25. if __name__ == "__main__":
  26. lock = multiprocessing.Lock()
  27. f = "file.txt"
  28. w = multiprocessing.Process(target = worker_with, args=(lock, f))
  29. nw = multiprocessing.Process(target = worker_no_with, args=(lock, f))
  30. w.start()
  31. nw.start()
  32. print "end"

输出结果:

  1. Lockd acquired via with
  2. Lockd acquired via with
  3. Lockd acquired via with
  4. Lockd acquired via with
  5. Lockd acquired via with
  6. Lockd acquired via with
  7. Lockd acquired via with
  8. Lockd acquired via with
  9. Lockd acquired via with
  10. Lock acquired directly
  11. Lock acquired directly
  12. Lock acquired directly
  13. Lock acquired directly
  14. Lock acquired directly
  15. Lock acquired directly
  16. Lock acquired directly
  17. Lock acquired directly
  18. Lock acquired directly

(2)multiprocess.Queue:实现进/线程间的同步

  • FIFO(先进先出)队列
  • LIFO(后进先出)队列
  • PriorityQueue(优先级)队列

注意:Queue.Queue是进程内非阻塞队列,multiprocess.Queue是跨进程通信队列。多进程前者是各自私有,后者是各子进程共有。

实例方法:

  1. Queue.qsize() 返回队列的大小
  2. Queue.empty() 如果队列为空,返回True,反之False
  3. Queue.full() 如果队列满了,返回True,反之False
  4. Queue.full maxsize 大小对应
  5. Queue.get([block[, timeout]])获取队列,timeout等待时间
  6. Queue.get_nowait() 相当Queue.get(False)
  7. Queue.put(item) 写入队列,timeout等待时间
  8. Queue.put_nowait(item) 相当Queue.put(item, False)
  9. Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
  10. Queue.join() 实际上意味着等到队列为空,再执行别的操作

FIFO(先进先出)队列:

  1. import Queue
  2.  
  3. q = Queue.Queue()
  4.  
  5. for i in range(5):
  6. q.put(i)
  7.  
  8. while not q.empty():
  9. print q.get()

  10. 输出结果:
  11.  
  12. 0
  13. 1
  14. 2
  15. 3
  16. 4

LIFO后进先出队列:

  1. import Queue
  2.  
  3. q = Queue.LifoQueue()
  4.  
  5. for i in range(5):
  6. q.put(i)
  7.  
  8. while not q.empty():
  9. print q.get()
  10. 输出结果:
  11.  
  12. 4
  13. 3
  14. 2
  15. 1

优先级队列:

  1. import Queue
  2. import threading
  3. import time
  4.  
  5. exitFlag = 0
  6.  
  7. class myThread (threading.Thread):
  8. def __init__(self, threadID, name, q):
  9. threading.Thread.__init__(self)
  10. self.threadID = threadID
  11. self.name = name
  12. self.q = q
  13. def run(self):
  14. print "Starting " + self.name
  15. process_data(self.name, self.q)
  16. print "Exiting " + self.name
  17.  
  18. def process_data(threadName, q):
  19. while not exitFlag:
  20. queueLock.acquire()
  21. if not workQueue.empty():
  22. data = q.get()
  23. queueLock.release()
  24. print "%s processing %s" % (threadName, data)
  25. else:
  26. queueLock.release()
  27. time.sleep(1)
  28.  
  29. threadList = ["Thread-1", "Thread-2", "Thread-3"]
  30. nameList = ["One", "Two", "Three", "Four", "Five"]
  31. queueLock = threading.Lock()
  32. workQueue = Queue.Queue(10)
  33. threads = []
  34. threadID = 1
  35.  
  36. # 创建新线程
  37. for tName in threadList:
  38. thread = myThread(threadID, tName, workQueue)
  39. thread.start()
  40. threads.append(thread)
  41. threadID += 1
  42.  
  43. # 填充队列
  44. queueLock.acquire()
  45. for word in nameList:
  46. workQueue.put(word)
  47. queueLock.release()
  48.  
  49. # 等待队列清空
  50. while not workQueue.empty():
  51. pass
  52.  
  53. # 通知线程是时候退出
  54. exitFlag = 1
  55.  
  56. # 等待所有线程完成
  57. for t in threads:
  58. t.join()
  59. print "Exiting Main Thread"

输出结果:

  1. Starting Thread-1
  2. Starting Thread-2
  3. Starting Thread-3
  4. Thread-1 processing One
  5. Thread-2 processing Two
  6. Thread-3 processing Three
  7. Thread-1 processing Four
  8. Thread-2 processing Five
  9. Exiting Thread-3
  10. Exiting Thread-1
  11. Exiting Thread-2
  12. Exiting Main Thread

 multiprocess.Queue:实现进程间的同步:

例1:

  1. from multiprocessing import Process,Queue
  2. def foo(q,n):
  3. q.put(n)
  4.  
  5. if __name__ == '__main__':
  6. que=Queue()
  7. for i in range(5):
  8. p=Process(target=foo,args=(que,i))
  9. p.start()
  10. p.join()
  11.  
  12. print(que.qsize())

输出结果:

  1. 5

例2:

  1. import multiprocessing
  2.  
  3. def writer_proc(q):
  4. try:
  5. q.put(1, block = False)
  6. except:
  7. pass
  8.  
  9. def reader_proc(q):
  10. try:
  11. print q.get(block = False)
  12. except:
  13. pass
  14.  
  15. if __name__ == "__main__":
  16. q = multiprocessing.Queue()
  17. writer = multiprocessing.Process(target=writer_proc, args=(q,))
  18. writer.start()
  19.  
  20. reader = multiprocessing.Process(target=reader_proc, args=(q,))
  21. reader.start()

输出结果:

  1. 1

(3)multiprocessing.Value与multiprocessing.Array:进行数据共享

  1. from multiprocessing import Process,Value,Array
  2.  
  3. def foo1(n,a):
  4. n.value = 3
  5. for i in range(len(a)):
  6. a[i] = -a[i]
  7.  
  8. if __name__ == '__main__':
  9. num = Value('d',0.0) #d的意思是小数.创建0.0
  10. arr = Array('i',range(10)) #i的意思是整数.创建一个0-9的整数
  11. p = Process(target=foo1,args=(num,arr))
  12. p.start()
  13. p.join()
  14. print num.value
  15. print arr[:]

输出结果:

  1. 3.0
  2. [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

(4)multiprocessing.Manager:数据共享

  1. from multiprocessing import Manager,Process
  2.  
  3. def f(d,l):
  4. d[1] = ''
  5. d[''] = 2
  6. d[0.25] = None
  7. l.reverse()
  8. if __name__ == '__main__':
  9. manage = Manager()
  10. d = manage.dict() #创建一个进程间可共享的dict
  11. l = manage.list(range(10)) #创建一个进程间可共享的list
  12. p = Process(target=f,args=(d,l))
  13. p.start()
  14. p.join()
  15. print d
  16. print l

输出结果:

  1. {0.25: None, 1: '', '': 2}
  2. [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

3.pool:如果需要多个子进程时可以考虑使用进程池(pool)来管理

Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

(1)使用进程池(非阻塞)

  1. #使用进程池(非阻塞)
  2. import time
  3. import multiprocessing
  4.  
  5. def fun(msg):
  6. print 'MSG:',msg
  7. time.sleep(3)
  8. print 'end'
  9. if __name__ == '__main__':
  10. pool = multiprocessing.Pool(processes=3)
  11. for i in xrange(4):
  12. msg = 'hello,%d' %(i)
  13. pool.apply_async(fun,(msg,)) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
  14. print '-----------------------'
  15. pool.close()
  16. pool.join()
  17. print 'Sub-processes done'

输出结果:

  1. -----------------------
  2. MSG: hello,0
  3. MSG: hello,1
  4. MSG: hello,2
  5. end
  6. MSG: hello,3
  7. end
  8. end
  9. end
  10. Sub-processes done

(2)使用进程池(阻塞)

  1. import time,multiprocessing
  2.  
  3. def fun(msg):
  4. print 'MSG:',msg
  5. time.sleep(3)
  6. print 'end'
  7. if __name__ == '__main__':
  8. pool = multiprocessing.Pool(processes=3)
  9. for i in xrange(4):
  10. msg = 'hello,%d' %i
  11. pool.apply(fun,(msg,))
  12. print '-------------------------------'
  13. pool.close()
  14. pool.join()
  15. print 'Sub-processes done'

输出结果:

  1. MSG: hello,0
  2. end
  3. MSG: hello,1
  4. end
  5. MSG: hello,2
  6. end
  7. MSG: hello,3
  8. end
  9. -------------------------------
  10. Sub-processes done

4.Pipe:用于具有亲缘关系进程间的通信,有名的管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;

实现机制:

管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。

  1. import multiprocessing
  2. import time
  3.  
  4. def proc1(pipe):
  5. while True:
  6. for i in range(10000):
  7. print 'send:%s' %i
  8. pipe.send(i)
  9. time.sleep(1)
  10.  
  11. def proc2(pipe):
  12. while True:
  13. print 'proc2 recv:',pipe.recv()
  14. time.sleep(1)
  15.  
  16. def proc3(pipe):
  17. while True:
  18. print 'proc3 recv:',pipe.recv()
  19. time.sleep(1)
  20.  
  21. if __name__ == '__main__':
  22. pipe = multiprocessing.Pipe()
  23. p1 = multiprocessing.Process(target=proc1,args=(pipe[0],))
  24. p2 = multiprocessing.Process(target=proc2, args=(pipe[1],))
  25. #p3 = multiprocessing.Process(target=proc3, args=(pipe[1],))
  26. p1.start()
  27. p2.start()
  28. #p3.start()
  29. p1.join()
  30. p2.join()
  31. #p3.join()

输出结果:

  1. send:0
  2. proc2 recv: 0
  3. send:1
  4. proc2 recv: 1
  5. send:2
  6. proc2 recv: 2
  7. send:3
  8. proc2 recv: 3
  9. send:4
  10. proc2 recv: 4
  11. send:5
  12. proc2 recv: 5
  13. send:6
  14. 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. Python之MySQL操作及Paramiko模块操作

    一.MySQL简介   MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQ ...

  2. 【Python】pymongo使用

    官方文档:http://api.mongodb.com/python/current/index.html MongoReplicaSetClient:http://api.mongodb.com/p ...

  3. PHP中获取当前页面的完整URL

    //获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br>"; #localhost//获取网页地址 echo $_SERVER['PHP ...

  4. 采用UDP协议的PIC32MZ ethernet bootloader

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 经过千辛万苦,今天终于 ...

  5. Leetcode5:Longest Palindromic Substring@Python

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  6. 9、SQL Server 操作数据

    插入数据 使用Insert Into 插入 if(exists(select * from sys.databases where name = 'webDB')) drop database web ...

  7. 微软第四题 给定cost能遍历的最大城市数

    有向图中N*N矩阵 cost:M, 最多可以遍历的结点个数 例如A可以有0->1->2->0->1 代价:2+2+3+2=9<10 输出4 #include <io ...

  8. Javascript 中 == 和 === 区别

    转载几张图片,说明其中的具体意义 这是 == 这是 === 完整比较图: 红色:=== 橙色:== 黄色:<= 和 >= 同时成立,== 不成立 蓝色:只有 >= 绿色:只有 < ...

  9. 移动端touch事件影响click事件以及在touchmove添加preventDefault导致页面无法滚动的解决方法

    这两天自己在写一个手机网页,用到了触屏滑动的特效,就是往右滑动的时候左侧隐藏的菜单从左边划出来. 做完之后在手机原生浏览器中运行正常,但在QQ和微信中打开,发现touchmove只会触发一次,而且to ...

  10. 使用JDBC访问SQLServer 2008

    使用JDBC访问SQLServer 2008 // 准备数据库驱动程序 String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriv ...