pythonmultiprocessing多进程(官⽅⽂档翻译)
⼀、简介
是⼀个和(多线程)类似的库,这个多进程库提供了远程和本地的并发,可以有效的解决thread⽆法解决的全局锁(GIL),正是由于这个模块,程序员能够充分利⽤多核CUP。同时这个模块⽀持Unix 和 Windows。
模块也提供了所没有的APIs,⼀个最简单的例⼦就是模块提供了了⼀个进程池(Pool)API,这个API可以很⽅便的将输⼊参数平均分配给不同的进程,从⽽我们定义的函数执⾏。下⾯这个就是⼀个很常见的⼩例⼦,这个例⼦使⽤的就是进程池(Pool):
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
p = Pool(5)
print(p.map(f, [1, 2, 3]))
[1, 4, 9]  #输出
1.1 类
模块中,processe类是⽤来创建⼀个进程的,并且可以调⽤它的⽅法。类也提供了的 API。下⾯是⼀个简单的例⼦。
from multiprocessing import Process
import os
def info(title):
print title
print 'module name:', __name__
if hasattr(os, 'getppid'):  # only available on Unix
print 'parent process:', os.getppid()
print 'process id:', os.getpid()
def f(name):
info('function f')
print 'hello', name
if __name__ == '__main__':
python官方文档中文版info('main line')
p = Process(target=f, args=('bob',))
p.start()
p.join()
main line
module name: __main__
process id: 136720
function f
module name: __main__
process id: 39448
hello bob
重点是  if__name__=='__main__' 绝对不可省略,⽽且你的多进程要放于这个下⾯,详情见
1.2 进程间的通讯
模块提供了两种不同的通信⽅式:
1、Queues
这个Queues实际上就是。
from multiprocessing import Process, Queue
def f(q):
q.put([42, None, 'hello'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
()    # prints "[42, None, 'hello']"
p.join()
Queues在多进程和多线程都是安全的。
2、Pipes
实际上是提供了⼀个管道连接,并且返回⼀对连接项,⽽且默认这个pipes是可以双向通信的。
from multiprocessing import Process, Pipe
def f(conn):
conn.send([42, None, 'hello'])
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print v()  # prints "[42, None, 'hello']"
p.join()
上⾯这个例⼦中,parent_conn,child_conn 就是 返回的⼀对连接项,分别代表这个管道的两端。这些连接项都有
和⽅法。值得注意的,当不同的进程(或线程)使⽤相同的连接项(即在同⼀端)同时向管道读取或者写⼊数据,将会出错。当然使⽤不同的连接项(通道的两端),则不会出错
1.3 进程间的同步
的同步机制和相同,下⾯的例⼦使⽤Lock来确保⼀次只有⼀个进程使⽤标准输出print:
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
print 'hello world', i
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
如果不使⽤LOCK,不同进程的结果就会混合在⼀起。
1.3 进程间的共享
当你在编写并发程序时,⼀定要尽可能的避免使⽤共享状态,特别对于多进程⽽⾔。
如果你真的要使⽤共享状态,也提供了⼀些⽅法。
1、共享内存
共享数据可以以值(Value)或者数组(Array)的形式存储在共享内存中:
from multiprocessing import Process, Value, Array
def f(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] = -a[i]
if __name__ == '__main__':
num = Value('d', 0.0)
arr = Array('i', range(10))
p = Process(target=f, args=(num, arr))
p.start()
p.join()
print num.value
print arr[:]
3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
d 和 i 能够被⼦进程共享使⽤,是因为它们是由 模块创建的,d 是⼀个双浮点型,i是⼀个整型,这些共享类型对线程和进程都是安全的。
当然,对于共享内存还有很多灵活的应⽤,模块能够创建其他类型的数据。
2、服务进程
Manager()能够创建⼀个管理项,这个管理项控制包含Python对象的服务器进程,并允许其他进程使⽤代理操作它们。
这个管理项⽀持的类型包括括:list,,,,,,,,,,
Value,。
from multiprocessing import Process, Manager
def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
if __name__ == '__main__':
manager = Manager()
d = manager.dict()
l = manager.list(range(10))
p = Process(target=f, args=(d, l))
p.start()
p.join()
print d
print l
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
进程服务管理器⽐共享内存灵活得多,因为它能够⽀持任意的数据类型,⼀个管理器能被多台电脑通过⽹络共享,但是它的速度要⽐共享内存慢得多。
1.4 使⽤进程池
Pool类表⽰⼀个⼯作进程池。它具有允许任务以⼏种不同的⽅式加载到⼯作进程中的⽅法。
from multiprocessing import Pool, TimeoutError
import time
import os
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=4)              # start 4 worker processes
# print "[0, 1, 4,..., 81]"
print pool.map(f, range(10))
# print same numbers in arbitrary order
for i in pool.imap_unordered(f, range(10)):
print i
# evaluate "f(20)" asynchronously
res = pool.apply_async(f, (20,))      # runs in *only* one process
(timeout=1)              # prints "400"
# evaluate "os.getpid()" asynchronously
res = pool.apply_pid, ()) # runs in *only* one process
(timeout=1)              # prints the PID of that process
# launching multiple evaluations asynchronously *may* use more processes
multiple_results = [pool.apply_pid, ()) for i in range(4)]
print [(timeout=1) for res in multiple_results]
# make a single worker sleep for 10 secs
res = pool.apply_async(time.sleep, (10,))
try:
(timeout=1)
except TimeoutError:
print "We lacked patience and got a multiprocessing.TimeoutError"
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
1
4
9
16
25
36
49
64
81
400
125384
[99128, 154040, 125384, 99128]
We lacked patience and got a multiprocessing.TimeoutError
注意,Pool的⽅法应该只能被创建它的进程使⽤。
注意:使⽤函数模块要求它的⼦进程能过导⼊__main__模块,这会在中讲到。
>>> from multiprocessing import Pool
>>> p = Pool(5)
>>> def f(x):
...    return x*x
...
>>> p.map(f, [1,2,3])
Process PoolWorker-1:
Process PoolWorker-2:
Process PoolWorker-3:
Traceback (most recent call last):
AttributeError: 'module' object has no attribute 'f'
AttributeError: 'module' object has no attribute 'f'
AttributeError: 'module' object has no attribute 'f'
假如你想尝试这个,它将会随机输出三个traceback,你也许不得不停下你的主程序。关于python  multiprocessing 的⽂档第⼀部分到此就结束了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。