Python多进程编程技术实例分析


Posted in Python onSeptember 16, 2014

本文以实例形式分析了Python多进程编程技术,有助于进一步Python程序设计技巧。分享给大家供大家参考。具体分析如下:

一般来说,由于Python的线程有些限制,例如多线程不能充分利用多核CPU等问题,因此在Python中我们更倾向使用多进程。但在做不阻塞的异步UI等场景,我们也会使用多线程。本篇文章主要探讨Python多进程的问题。

Python在2.6引入了多进程的机制,并提供了丰富的组件及api以方便编写并发应用。multiprocessing包的组件Process, Queue, Pipe, Lock等组件提供了与多线程类似的功能。使用这些组件,可以方便地编写多进程并发程序。

Process

Process的使用有点像java.lang.Thread,但Thread是线程。start方法用以启动某个进程。一个简单的示例:

from multiprocessing import Process
import os
import time
def sleeper(name, seconds):
  print "Process ID# %s" % (os.getpid())
  print "Parent Process ID# %s" % (os.getppid())
  print "%s will sleep for %s seconds" % (name, seconds)
  time.sleep(seconds)

if __name__ == "__main__":
  child_proc = Process(target=sleeper, args=('bob', 5))
  child_proc.start()
  print "in parent process after child process start"
  print "parent process abount to join child process"
  child_proc.join()
  print "in parent process after child process join"
  print "the parent's parent process: %s" % (os.getppid())

实例化一个Process必须要指定target和args。target是新的进程的入口方法,可以认为是main方法。args是该方法的参数列表。启动进程类似于启动Thread,必须要调用start方法。也可以继承Process,覆盖run方法,在run方法中实现该进程的逻辑。调用join方法会阻塞当前调用进程,直到被调用进程运行结束。
手工终止一个进程可以调用terminate方法,在UNIX系统中,该方法会发送SIGTERM信号量,而在windows系统中,会借助TerminateProcess方法。需要注意的是,exit处理逻辑并不会被执行,该进程的子进程不会被终止,他们只会变成孤儿进程。

Queue

Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。

get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常。Queue的一段示例代码:

from multiprocessing import Process, Queue
def offer(queue):
  queue.put("Hello World")
def test(queue, num):
  queue.put("Hello World: " + str(num))
if __name__ == '__main__':
  q = Queue()
  p1 = Process(target=test, args=(q, 1))
  p1.start()
  p = Process(target=offer, args=(q,))
  p.start()
  p2 = Process(target=test, args=(q, 2))
  p2.start()
  p2 = Process(target=test, args=(q, 3))
  p2.start()
  print q.get()
  print q.get()
  print q.get()
  print q.get()
  print q.close()

输出:

Hello World: 1
Hello World
Hello World: 2
None

Pipes

Pipe方法返回(conn1, conn2)代表一个管道的两个端。Pipe方法有duplex参数,如果duplex参数为True(默认值),那么这个管道是全双工模式,也就是说conn1和conn2均可收发。duplex为False,conn1只负责接受消息,conn2只负责发送消息。

send和recv方法分别是发送和接受消息的方法。例如,在全双工模式下,可以调用conn1.send发送消息,conn1.recv接收消息。如果没有消息可接收,recv方法会一直阻塞。如果管道已经被关闭,那么recv方法会抛出EOFError。

from multiprocessing import Process, Pipe

def send(conn):
  conn.send("Hello World")
  conn.close()
if __name__ == '__main__':
  parent_conn, child_conn = Pipe()
  p = Process(target=send, args=(child_conn,))
  p.start()
  print parent_conn.recv()

同步

multiprocessing包提供了Condition, Event, Lock, RLock, Semaphore等组件可用于同步。下面是使用Lock的一个示例:

from multiprocessing import Process, Lock
def l(lock, num):
  lock.acquire() 
  print "Hello Num: %s" % (num)
  lock.release()
if __name__ == '__main__':
  lock = Lock()
for num in range(20):
  Process(target=l, args=(lock, num)).start()

总结

以上是Python multiprocessing库的简单介绍和实例,熟悉Java多线程开发的同学是不是觉得很熟悉,和java的Concurrency API很像,不过javaConcurrency是处理多线程的而已,我们可以直接按照以前Java多线程的经验用这些API。

感兴趣的朋友可以测试运行本文实例以加深理解。相信本文所述对大家Python程序设计的学习有一定的借鉴价值。

Python 相关文章推荐
Python中查看文件名和文件路径
Mar 31 Python
python+selenium+autoit实现文件上传功能
Aug 23 Python
Python实现KNN邻近算法
Jan 28 Python
python如何实现反向迭代
Mar 20 Python
python 显示数组全部元素的方法
Apr 19 Python
Python 忽略warning的输出方法
Oct 18 Python
在pandas多重索引multiIndex中选定指定索引的行方法
Nov 16 Python
Python3 使用pillow库生成随机验证码
Aug 26 Python
python requests证书问题解决
Sep 05 Python
python实现数据结构中双向循环链表操作的示例
Oct 09 Python
Python之字符串的遍历的4种方式
Dec 08 Python
Selenium浏览器自动化如何上传文件
Apr 06 Python
Python专用方法与迭代机制实例分析
Sep 15 #Python
跟老齐学Python之有容乃大的list(3)
Sep 15 #Python
跟老齐学Python之有容乃大的list(2)
Sep 15 #Python
跟老齐学Python之有容乃大的list(1)
Sep 14 #Python
跟老齐学Python之一个免费的实验室
Sep 14 #Python
跟老齐学Python之从if开始语句的征程
Sep 14 #Python
跟老齐学Python之眼花缭乱的运算符
Sep 14 #Python
You might like
php 无限极分类
2008/03/27 PHP
深入PHP购物车模块功能分析(函数讲解,附源码)
2013/06/25 PHP
PHP动态规划解决0-1背包问题实例分析
2015/03/23 PHP
Linux下编译redis和phpredis的方法
2016/04/07 PHP
php修改数组键名的方法示例
2017/04/15 PHP
PHP实现针对日期,月数,天数,周数,小时,分,秒等的加减运算示例【基于strtotime】
2017/04/19 PHP
php批量删除操作(数据访问)
2017/05/23 PHP
PHP使用Curl实现模拟登录及抓取数据功能示例
2018/04/27 PHP
PHP实现动态压缩js与css文件的方法
2018/05/02 PHP
红米手机抢购的js代码
2014/03/10 Javascript
jQuery插件bxSlider实现响应式焦点图
2015/04/12 Javascript
javascript小数精度丢失的完美解决方法
2016/05/31 Javascript
BootStrap table使用方法分析
2016/11/08 Javascript
[原创]SyntaxHighlighter自动识别并加载脚本语言
2017/02/07 Javascript
JavaScript字符串转数字的5种方法及遇到的坑
2018/07/16 Javascript
BootstrapValidator验证用户名已存在(ajax)
2019/11/08 Javascript
微信小程序12行js代码自己写个滑块功能(推荐)
2020/07/15 Javascript
JavaScript Image对象实现原理实例解析
2020/08/26 Javascript
Python程序语言快速上手教程
2012/07/18 Python
使用Python的Twisted框架编写简单的网络客户端
2015/04/16 Python
Python基于jieba库进行简单分词及词云功能实现方法
2018/06/16 Python
python实现求两个字符串的最长公共子串方法
2018/07/20 Python
Python一个简单的通信程序(客户端 服务器)
2019/03/06 Python
Python实现带下标索引的遍历操作示例
2019/05/30 Python
css3的transition效果和transfor效果示例介绍
2013/10/30 HTML / CSS
军人违纪检讨书
2014/02/04 职场文书
档案室主任岗位职责
2014/02/12 职场文书
环保倡议书400字
2014/05/15 职场文书
文秘自荐信
2014/06/28 职场文书
市政工程技术专业自荐书
2014/07/06 职场文书
商务邀请函
2015/01/30 职场文书
2015年数学教研工作总结
2015/07/22 职场文书
《风不能把阳光打败》读后感3篇
2020/01/06 职场文书
Python异常类型以及处理方法汇总
2021/06/05 Python
美国运营商 T-Mobile 以 117.83Mb/s 的速度排第一位
2022/04/21 数码科技
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js