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绘图库Matplotlib的安装
Jul 03 Python
Python发送email的3种方法
Apr 28 Python
python安装oracle扩展及数据库连接方法
Feb 21 Python
Flask解决跨域的问题示例代码
Feb 12 Python
Python 编码规范(Google Python Style Guide)
May 05 Python
对Pandas DataFrame缺失值的查找与填充示例讲解
Nov 06 Python
Python3 单行多行万能正则匹配方法
Jan 07 Python
python requests指定出口ip的例子
Jul 25 Python
python 提取文件指定列的方法示例
Aug 07 Python
教你用python实现一个无界面的小型图书管理系统
May 21 Python
Python实现随机生成迷宫并自动寻路
Jun 13 Python
python使用pycharm安装pyqt5以及相关配置
Apr 22 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生成缩略图的函数代码(修改版)
2011/01/18 PHP
CodeIgniter中实现泛域名解析
2014/07/19 PHP
PHP实现全角字符转为半角方法汇总
2015/07/09 PHP
详解WordPress中提醒安装插件以及隐藏插件的功能实现
2015/12/25 PHP
php解析mht文件转换成html的实例
2017/03/13 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
2018/08/21 PHP
php 处理png图片白色背景色改为透明色的实例代码
2018/12/10 PHP
laravel框架 laravel-admin上传图片到oss的方法
2019/10/13 PHP
jQuery 表单验证插件formValidation实现个性化错误提示
2009/06/23 Javascript
picChange 图片切换特效的函数代码
2010/05/06 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
Backbone.js框架中简单的View视图编写学习笔记
2016/02/14 Javascript
Node.js Sequelize如何实现数据库的读写分离
2016/10/23 Javascript
js实现PC端根据IP定位当前城市地理位置
2017/02/22 Javascript
JavaScript中十种一步拷贝数组的方法实例详解
2019/04/22 Javascript
关于layui 下拉列表的change事件详解
2019/09/20 Javascript
微信小程序input抖动问题的修复方法
2021/03/03 Javascript
[02:53]DOTA2亚洲邀请赛 NewBee战队巡礼
2015/02/03 DOTA
[01:13:18]Secret vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
Python中使用hashlib模块处理算法的教程
2015/04/28 Python
Python中的rfind()方法使用详解
2015/05/19 Python
python动态加载包的方法小结
2016/04/18 Python
Python常见读写文件操作实例总结【文本、json、csv、pdf等】
2019/04/15 Python
python实现多线程端口扫描
2019/08/31 Python
Django继承自带user表并重写的例子
2019/11/18 Python
通过celery异步处理一个查询任务的完整代码
2019/11/19 Python
解决redis与Python交互取出来的是bytes类型的问题
2020/07/16 Python
python如何绘制疫情图
2020/09/16 Python
python模拟点击玩游戏的实例讲解
2020/11/26 Python
浅谈关于html5中图片抛物线运动的一些心得
2018/01/09 HTML / CSS
素质拓展感言
2014/01/29 职场文书
大学生村官座谈会发言材料
2014/05/25 职场文书
党的群众路线教育实践活动整改落实情况自查报告
2014/10/28 职场文书
2014年学生党支部工作总结
2014/12/20 职场文书
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏
Go并发4种方法简明讲解
2022/04/06 Golang