持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
一、简介
multiprocessing模块 (MP) 产生子进程而不是线程 。可用于数据并行性——通过跨进程分布数据来并行执行跨多个输入值的函数。
2.使用方法
import multiprocessing as mp
def foo(q):
pass
if __name__ == '__main__':
# using get_context() is preferred over set_start_method().
ctx = mp.get_context('spawn') # multiprocessing具有自定义上下文对象的类型
q = ctx.Queue()
p = ctx.Process(target=foo, args=(q,))
set_start_method()不建议在程序中多次使用。
2.1. spawn
父进程每次都会启动一个新的 python 解释器。这是最慢的选项。仅继承方法所需的那些对象multiprocessing.Process.run。
2.2. fork
父进程使用os.fork(). 父进程的所有资源都由子进程继承。这比生成更快。
“如果在多线程进程上使用不安全”(我认为这意味着如果我们也在使用该模块,则不应使用此方法 threading?)。总的来说,fork start 方法会导致子进程崩溃,因此是不安全的。
这仅在 Unix 上可用。
2.3. forkserver
当程序启动时,使用这种方法,也会启动一个服务器进程。每次请求时,fork 服务器都可以 fork 一个新进程。fork 进程服务器是单线程的,因此可以安全地使用os.fork(). 不会从父进程继承不必要的资源。
与 类似fork,这仅在 Unix 上可用。
2.4. 结论
我可以在我的项目里使用forkserver
3.进程之间的通信
multiprocessing 允许在进程之间交换对象。
3.1。队列
使用multiprocessing.Queue而不是queue.Queue.
脚步:
- 使用创建队列
q = multiprocessing.Queue()。 q.put([1, 'a', 2])将列表[1, 'a', 2]放入队列。q.get()检索放入队列中的任何内容(我认为它按 FIFO 顺序检索?)。这可以与另一个函数结合使用,len(q.get())以获取列表的长度。
import multiprocessing as mp
q = mp.Queue()
print(q)
q.put([1, 'a', 2])
print(len(q.get()))
3.1.1。将多个队列放入(?)单个进程中
- 使用 启动一个进程
p = mp.Process(target=putter, arg=q),其中putter将对象放入队列q中。 - 启动进程:
p.start()。 - 中间操作,例如从队列中请求事物。
- 进程终止后加入:
p.join().
def putter(q: mp.queues.Queue, value):
q.put(value)
if __name__ == '__main__':
q: mp.queues.Queue = mp.Queue()
p: mp.Process = mp.Process(target=putter, args=(q, [42, None, 'hello']))
p.start()
print(q.get()) # "[42, None, 'hello']"
# print(q.get) # 再次运行它会因为某种原因而阻塞进程。
p.join()
3.2. 管道
该Pipe()函数通过返回一对连接对象来返回双向连接。
每个连接对象都有一个send()andrecv()方法。