当前位置: 移动技术网 > IT编程>脚本编程>Python > Python多进程编程技术实例分析

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

2019年03月26日  | 移动技术网IT编程  | 我要评论

养牛知识,保罗·韦斯利妻子,gbl

本文以实例形式分析了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程序设计的学习有一定的借鉴价值。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网