multiprocessing
Process Pools
1. apply (func[, args[, kwds]])
- 只能执行1次(只能输入一次参数)
- 支持多个参数(参数统一为元祖类型)
- 阻塞(只能等待这行代码执行完,才会执行下面的代码)
- 返回结果为函数执行结果
2. apply_async (func[, args[, kwds[, callback[, error_callback]]]])
- 异步,不阻塞(子进程先跑着,会接着执行主进程代码)
- 返回结果为 AsyncResult, 可查看结果有没有准备好,使用.get()获取结果
3. map (func, iterable[, chunksize])
- 可多次函数(迭代参数)
- 目标函数只支持 单参数 输入
- 阻塞
- 返回结果为list,顺序与输入的参数迭代器的顺序一致
4. map_async (func, iterable[, chunksize[, callback[, error_callback]]])
- 异步,不阻塞
- 返回结果为 AsyncResult
5. imap(func, iterable[, chunksize])
- 异步,不阻塞
- 输出为迭代器,不是list,顺序和输入参数一致
6. imap_unordered (func, iterable[, chunksize])
- 输出为迭代器,乱序
7. starmap (func, iterable[, chunksize])
- 支持目标函数为多参数:Demo iterable: [(1,2), (3, 4)]
8. starmap_async (func, iterable[, chunksize[, callback[, error_callback]]])
- 异步,不阻塞
9. close()
- 关闭池口,不允许再向池内添加任务
- 所有任务完成后,子进程都将自动退出
10. terminate()
- 立即终止某个子进程
11. join()
- 等待所有子进程完成后,退出
Example
from multiprocessing import Pool
def add(a, b):
return a + b
if __name__ == '__main__':
with Pool(processes=4) as pool:
results = pool.starmap_async(add, [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10), (11, 12), (13, 14)])
while not results.ready():
# Do other work while waiting for results
pass
output = results.get()
print(output)
Lock
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
try:
print('hello world', i)
finally:
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
进程间通信
队列 Queue
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()
print(q.get()) # prints "[42, None, 'hello']"
p.join()
管道 Pipe
Pipe() 函数返回一个由管道连接的连接对象,默认情况下是双工(双向)。例如:
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(parent_conn.recv()) # prints "[42, None, 'hello']"
p.join()
返回的两个连接对象 Pipe() 表示管道的两端。每个连接对象都有 send() 和 recv() 方法(相互之间的)。请注意,如果两个进程(或线程)同时尝试读取或写入管道的 同一 端,则管道中的数据可能会损坏。当然,在不同进程中同时使用管道的不同端的情况下不存在损坏的风险。