python multiprocessing 类与方法集合

multiprocessing 官方文档:https://docs.python.org/zh-cn/3.7/library/multiprocessing.html#module-multiprocessing.pool

 

 

功能概述(建议先看下方的方法集合后再回头看)

Process 

上下文和启动方法

在进程之间通信

进程之间的同步

在进程之间共享状态

使用工作进程

 

Process 

class multiprocessing.Process(group=Nonetarget=Nonename=Noneargs=()kwargs={}*daemon=None)

run() 表示进程活动的方法

start()

启动进程活动。

join([timeout])

如果可选参数 timeout  None (默认值),则该方法将阻塞,直到调用 join() 方法的进程终止。如果 timeout 是一个正数,它最多会阻塞 timeout 秒。请注意,如果进程终止或方法超时,则该方法返回 None 。检查进程的 exitcode 以确定它是否终止。

name

进程的名称。该名称是一个字符串,仅用于识别目的。它没有语义。可以为多个进程指定相同的名称。

 

is_alive()

返回进程是否还活着。

daemon

进程的守护标志,一个布尔值。这必须在 start() 被调用之前设置。

pid

返回进程ID。在生成该进程之前,这将是 None 

exitcode

的退子进程出代码。如果进程尚未终止,这将是 None 。负值 -N 表示孩子被信号 N 终止。

authkey

进程的身份验证密钥(字节字符串)。

sentinel

系统对象的数字句柄,当进程结束时将变为 "ready"

terminate()

终止进程。 Unix上,这是使用 SIGTERM 信号完成的;在Windows上使用 TerminateProcess()  请注意,不会执行退出处理程序和finally子句等。

kill()

 terminate() 相同,但在Unix上使用 SIGKILL 信号。

close()

关闭 Process 对象,释放与之关联的所有资源。

 

异常类型:

exception multiprocessing.ProcessError

所有 multiprocessing 异常的基类。

exception multiprocessing.BufferTooShort

当提供的缓冲区对象太小而无法读取消息时, Connection.recv_bytes_into() 引发的异常。

如果 e 是一个 BufferTooShort 实例,那么 e.args[0] 将把消息作为字节字符串给出。

exception multiprocessing.AuthenticationError

出现身份验证错误时引发。

exception multiprocessing.TimeoutError

有超时的方法超时时引发。

管道和队列

 

multiprocessing.Pipe([duplex])

返回一对 Connection`对象  ``(conn1, conn2)`  分别表示管道的两端。

class multiprocessing.Queue([maxsize])

返回一个使用一个管道和少量锁和信号量实现的共享队列实例。当一个进程将一个对象放进队列中时,一个写入线程会启动并将对象从缓冲区写入管道中。

qsize()

返回队列的大致长度。由于多线程或者多进程的上下文,这个数字是不可靠的。

empty()

如果队列是空的,返回 True ,反之返回 False  由于多线程或多进程的环境,该状态是不可靠的。

full()

如果队列是满的,返回 True ,反之返回 False  由于多线程或多进程的环境,该状态是不可靠的。

put(obj[block[timeout]])

obj 放入队列。如果可选参数 block  True (默认值) 而且 timeout  None (默认值), 将会阻塞当前进程,直到有空的缓冲槽。如果 timeout 是正数,将会在阻塞了最多 timeout 秒之后还是没有可用的缓冲槽时抛出 queue.Full  异常。反之 (block  False ),仅当有可用缓冲槽时才放入对象,否则抛出 queue.Full 异常 (在这种情形下 timeout 参数会被忽略)

put_nowait(obj)

相当于 put(obj, False)

get([block[timeout]])

从队列中取出并返回对象。如果可选参数 block  True (默认值) 而且 timeout  None (默认值), 将会阻塞当前进程,直到队列中出现可用的对象。如果 timeout 是正数,将会在阻塞了最多 timeout 秒之后还是没有可用的对象时抛出 queue.Empty 异常。反之 (block  False ),仅当有可用对象能够取出时返回,否则抛出 queue.Empty 异常 (在这种情形下 timeout 参数会被忽略)

get_nowait()

相当于 get(False) 

close()

指示当前进程将不会再往队列中放入对象。一旦所有缓冲区中的数据被写入管道之后,后台的线程会退出。这个方法在队列被gc回收时会自动调用。

join_thread()

等待后台线程。这个方法仅在调用了 close() 方法之后可用。这会阻塞当前进程,直到后台线程退出,确保所有缓冲区中的数据都被写入管道中。

cancel_join_thread()

防止 join_thread() 方法阻塞当前进程。具体而言,这防止进程退出时自动等待后台线程退出。详见 join_thread()

class multiprocessing.SimpleQueue

这是一个简化的 Queue 类的实现,很像带锁的 Pipe 

empty()

如果队列为空返回 True ,否则返回 False 

get()

从队列中移出并返回一个对象。

put(item)

 item 放入队列。

 

class multiprocessing.JoinableQueue([maxsize])

JoinableQueue 类是 Queue 的子类,额外添加了 task_done()  join() 方法。

task_done()

指出之前进入队列的任务已经完成。由队列的消费者进程使用。对于每次调用 get() 获取的任务,执行完成后调用 task_done() 告诉队列该任务已经处理完成。

如果 join() 方法正在阻塞之中,该方法会在所有对象都被处理完的时候返回 (即对之前使用 put() 放进队列中的所有对象都已经返回了对应的 task_done() )

如果被调用的次数多于放入队列中的项目数量,将引发 ValueError 异常

join()

阻塞至队列中所有的元素都被接收和处理完毕。

当条目添加到队列的时候,未完成任务的计数就会增加。每当消费者进程调用 task_done() 表示这个条目已经被回收,该条目所有工作已经完成,未完成计数就会减少。当未完成计数降到零的时候, join() 阻塞被解除。

杂项

multiprocessing.active_children()

返回当前进程存活的子进程的列表。

调用该方法有等待已经结束的进程的副作用。

multiprocessing.cpu_count()

返回系统的CPU数量。

该数量不同于当前进程可以使用的CPU数量。可用的CPU数量可以由 len(os.sched_getaffinity(0)) 方法获得。

multiprocessing.current_process()

返回与当前进程相对应的 Process 对象。

multiprocessing.freeze_support()

为使用了 multiprocessing  的程序,提供冻结以产生 Windows 可执行文件的支持

需要在 main 模块的 if __name__ == '__main__' 该行之后马上调用该函数。

如果没有调用 freeze_support() 在尝试运行被冻结的可执行文件时会抛出 RuntimeError 异常。

ultiprocessing.get_all_start_methods()

返回支持的启动方法的列表,该列表的首项即为默认选项。可能的启动方法有 'fork''spawn' ``'forkserver'。在 Windows 中,只有  ``'spawn' 是可用的。

 

multiprocessing.get_context(method=None)

返回一个 Context 对象。该对象具有和 multiprocessing 模块相同的API

 

multiprocessing.get_start_method(allow_none=False)

返回启动进程时使用的启动方法名。

 

multiprocessing.set_executable()

设置在启动子进程时使用的 Python 解释器路径。 ( 默认使用 sys.executable ) 嵌入式编程人员可能需要这样做:

set_executable(os.path.join(sys.exec_prefix, 'pythonw.exe'))

multiprocessing.set_start_method(method)

设置启动子进程的方法。 method 可以是 'fork' , 'spawn' 或者 'forkserver' 

连接对象(Connection

class multiprocessing.connection.Connection

通常使用 Pipe 创建 Connection 对象。

send(obj)

将一个对象发送到连接的另一端,可以用 recv() 读取。

发送的对象必须是可以序列化的

recv()

返回一个由另一端使用 send() 发送的对象。该方法会一直阻塞直到接收到对象。 如果对端关闭了连接或者没有东西可接收,将抛出 EOFError  异常。

fileno()

返回由连接对象使用的描述符或者句柄。

close()

关闭连接对象。

当连接对象被垃圾回收时会自动调用。

poll([timeout])

返回连接对象中是否有可以读取的数据。

如果未指定 timeout ,此方法会马上返回。如果 timeout 是一个数字,则指定了最大阻塞的秒数。如果 timeout  None  ,那么将一直等待,不会超时。

注意通过使用 multiprocessing.connection.wait() 可以一次轮询多个连接对象。

 

send_bytes(buffer[offset[size]])

从一个 bytes-like object  (字节类对象)对象中取出字节数组并作为一条完整消息发送。

如果由 offset  给定了在 buffer 中读取数据的位置。 如果给定了 size ,那么将会从缓冲区中读取多个字节。

recv_bytes([maxlength])

以字符串形式返回一条从连接对象另一端发送过来的字节数据。此方法在接收到数据前将一直阻塞。 如果连接对象被对端关闭或者没有数据可读取,将抛出 EOFError  异常。

如果给定了 maxlength 并且消息长于 maxlength 那么将抛出 OSError 并且该连接对象将不再可读。

recv_bytes_into(buffer[offset])

将一条完整的字节数据消息读入 buffer 中并返回消息的字节数。 此方法在接收到数据前将一直阻塞。 如果连接对象被对端关闭或者没有数据可读取,将抛出 EOFError  异常。

 

警告

如果一个进程在试图读写管道时被终止了,那么管道中的数据很可能是不完整的,因为此时可能无法确定消息的边界。

同步原语

class multiprocessing.Barrier(parties[action[timeout]])

类似 threading.Barrier 的栅栏对象。

 

class multiprocessing.BoundedSemaphore([value])

非常类似 threading.BoundedSemaphore 的有界信号量对象。

class multiprocessing.Condition([lock])

条件变量: threading.Condition 的别名。

class multiprocessing.Event

A clone of threading.Event.

class multiprocessing.Lock

原始锁(非递归锁)对象,类似于 threading.Lock 。一旦一个进程或者线程拿到了锁,后续的任何其他进程或线程的其他请求都会被阻塞直到锁被释放。任何进程或线程都可以释放锁。除非另有说明,否则 multiprocessing.Lock  用于进程或者线程的概念和行为都和 threading.Lock  一致。

acquire(block=Truetimeout=None)

可以阻塞或非阻塞地获得锁。

 

release()

释放锁,可以在任何进程、线程使用,并不限于锁的拥有者。

 

class multiprocessing.RLock

递归锁对象: 类似于 threading.RLock 。递归锁必须由持有线程、进程亲自释放。如果某个进程或者线程拿到了递归锁,这个进程或者线程可以再次拿到这个锁而不需要等待。但是这个进程或者线程的拿锁操作和释放锁操作的次数必须相同。

 

acquire(block=Truetimeout=None)

可以阻塞或非阻塞地获得锁。

release()

释放锁,使锁内的递归等级减一。如果释放后锁内的递归等级降低为0,则会重置锁的状态为释放状态(即没有被任何进程、线程持有)

 

class multiprocessing.Semaphore([value])

一种信号量对象: 类似于 threading.Semaphore.

 

共享 ctypes 对象(共享内存)

在共享内存上创建可被子进程继承的共享对象时是可行的。

multiprocessing.Value(typecode_or_type*argslock=True)

返回一个从共享内存上创建的 ctypes 对象。默认情况下返回的实际上是经过了同步包装器包装过的。可以通过 Value  value 属性访问这个对象本身。

multiprocessing.Array(typecode_or_typesize_or_initializer*lock=True)

从共享内存中申请并返回一个具有ctypes类型的数组对象。默认情况下返回值实际上是被同步器包装过的数组对象。

 

multiprocessing.sharedctypes 模块

multiprocessing.sharedctypes 模块提供了一些函数,用于分配来自共享内存的、可被子进程继承的 ctypes 对象。

multiprocessing.sharedctypes.RawArray(typecode_or_typesize_or_initializer)

从共享内存中申请并返回一个 ctypes 数组。

 

multiprocessing.sharedctypes.Array(typecode_or_typesize_or_initializer*lock=True)

返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的对象,这取决于 lock 参数的值,除此之外,和 RawArray() 一样。

 

multiprocessing.sharedctypes.Value(typecode_or_type*argslock=True)

返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的进程安全的对象,这取决于 lock 参数的值,除此之外,和 RawArray() 一样。

 

ultiprocessing.sharedctypes.copy(obj)

从共享内存中申请一片空间将 ctypes 对象 obj 过来,然后返回一个新的 ctypes 对象。

 

multiprocessing.sharedctypes.synchronized(obj[lock])

将一个 ctypes 对象包装为进程安全的对象并返回,使用 lock 同步对于它的操作。如果 lock  None (默认值) ,则会自动创建一个 multiprocessing.RLock 对象。

 

 

下面的表格对比了创建普通ctypes对象和基于共享内存上创建共享ctypes对象的语法。(表格中的 MyStruct  ctypes.Structure 的子类)

ctypes

使用类型的共享ctypes

使用 typecode 的共享 ctypes

c_double(2.4)

RawValue(c_double, 2.4)

RawValue('d', 2.4)

MyStruct(4, 6)

RawValue(MyStruct, 4, 6)

 

(c_short * 7)()

RawArray(c_short, 7)

RawArray('h', 7)

(c_int * 3)(9, 2, 8)

RawArray(c_int, (9, 2, 8))

RawArray('i', (9, 2, 8))

 

 

数据管理器

管理器提供了一种创建共享数据的方法,从而可以在不同进程中共享,甚至可以通过网络跨机器共享数据。管理器维护一个用于管理 共享对象 的服务。其他进程可以通过代理访问这些共享对象。

 

multiprocessing.Manager()

返回一个已启动的 SyncManager 管理器对象,这个对象可以用于在不同进程中共享数据。返回的管理器对象对应了一个 spawned 方式启动的子进程,并且拥有一系列方法可以用于创建共享对象、返回对应的代理。

 

class multiprocessing.managers.BaseManager([address[authkey]])

创建一个 BaseManager 对象。

一旦创建,应该及时调用 start() 或者 get_server().serve_forever() 以确保管理器对象对应的管理进程已经启动。

start([initializer[initargs]])

为管理器开启一个子进程,如果 initializer 不是 None , 子进程在启动时将会调用 initializer(*initargs) 

get_server()

返回一个 Server  对象,它是管理器在后台控制的真实的服务。 Server  对象拥有 serve_forever() 方法。

connect()

将本地管理器对象连接到一个远程管理器进程:

shutdown()

停止管理器的进程。这个方法只能用于已经使用 start() 启动的服务进程。

register(typeid[callable[proxytype[exposed[method_to_typeid[create_method]]]]])

一个 classmethod,可以将一个类型或者可调用对象注册到管理器类。

address

管理器所用的地址。

class multiprocessing.managers.SyncManager

BaseManager 的子类,可用于进程的同步。这个类型的对象使用 multiprocessing.Manager() 创建。

 

Barrier(parties[action[timeout]])

创建一个共享的 threading.Barrier 对象并返回它的代理。

BoundedSemaphore([value])

创建一个共享的 threading.BoundedSemaphore 对象并返回它的代理。

 

Condition([lock])

创建一个共享的 threading.Condition 对象并返回它的代理。

Event()

创建一个共享的 threading.Event 对象并返回它的代理。

Lock()

创建一个共享的 threading.Lock 对象并返回它的代理。

Namespace()

创建一个共享的 Namespace` 对象并返回它的代理。

Queue([maxsize])

创建一个共享的 queue.Queue 对象并返回它的代理。

RLock()

创建一个共享的 threading.RLock 对象并返回它的代理。

Semaphore([value])

创建一个共享的 threading.Semaphore 对象并返回它的代理。

Array(typecodesequence)

创建一个数组并返回它的代理。

Value(typecodevalue)

创建一个具有可写 value 属性的对象并返回它的代理。

dict()

dict(mapping)

dict(sequence)

创建一个共享的 dict 对象并返回它的代理。

list()

list(sequence)

创建一个共享的 list 对象并返回它的代理。

 

class multiprocessing.managers.Namespace

一个可以注册到 SyncManager 的类型。

 

自定义管理器

 

要创建一个自定义的管理器,需要新建一个 BaseManager 的子类,然后使用这个管理器类上的 register() 类方法将新类型或者可调用方法注册上去。

 

使用远程管理器

可以将管理器服务运行在一台机器上,然后使用客户端从其他机器上访问。(假设它们的防火墙允许这样的网络通信)

 

代理对象

代理是一个 指向 其他共享对象的对象,这个对象(很可能)在另外一个进程中。共享对象也可以说是代理 指涉 的对象。多个代理对象可能指向同一个指涉对象。

 

class multiprocessing.managers.BaseProxy

代理对象是 BaseProxy 派生类的实例。

 

_callmethod(methodname[args[kwds]])

调用指向对象的方法并返回结果。

_getvalue()

返回指涉对象的一份拷贝。

如果指涉对象无法序列化,则会抛出一个异常。

__repr__()

返回代理对象的字符串表示。

__str__()

返回指涉对象的字符串表示。

 

清理

代理对象使用了一个弱引用回调,当它被垃圾回收时,会将自己从拥有此指涉对象的管理器上反注册,

当共享对象没有被任何代理器引用时,会被管理器进程删除。

 

 

进程池

可以创建一个进程池,它将使用 Pool 类执行提交给它的任务。

 

class multiprocessing.pool.Pool([processes[initializer[initargs[maxtasksperchild[context]]]]])

一个进程池对象,它控制可以提交作业的工作进程池。它支持带有超时和回调的异步结果,以及一个并行的 map 实现。

apply(func[args[kwds]])

使用 args 参数以及 kwds 命名参数调用 func , 它会返回结果前阻塞。这种情况下,apply_async() 更适合并行化工作。另外 func 只会在一个进程池中的一个工作进程中执行。

apply_async(func[args[kwds[callback[error_callback]]]])

apply() 方法的一个变种,返回一个结果对象。

map(funciterable[chunksize])

内置 map() 函数的并行版本 (但它只支持一个 iterable 参数,对于多个可迭代对象请参阅 starmap()) 它会保持阻塞直到获得结果。

map_async(funciterable[chunksize[callback[error_callback]]])

 map() 方法类似,但是返回一个结果对象。

imap(funciterable[chunksize])

map() 的延迟执行版本。

 

imap_unordered(funciterable[chunksize])

 imap() 相同,只不过通过迭代器返回的结果是任意的。(当进程池中只有一个工作进程的时候,返回结果的顺序才能认为是"有序"的)

 

starmap(funciterable[chunksize])

 map() 类似,不过 iterable 中的每一项会被解包再作为函数参数。

starmap_async(funciterable[chunksize[callback[error_callback]]])

相当于 starmap()  map_async() 的结合,迭代 iterable 的每一项,解包作为 func 的参数并执行,返回用于获取结果的对象。

 

close()

阻止后续任务提交到进程池,当所有任务执行完成后,工作进程会退出。

terminate()

不必等待未完成的任务,立即停止工作进程。当进程池对象呗垃圾回收时, terminate() 会立即调用。

join()

等待工作进程结束。调用 join() 前必须先调用 close() 或者 terminate() 

 

class multiprocessing.pool.AsyncResult

Pool.apply_async()  Pool.map_async() 返回对象所属的类。

get([timeout])

用于获取执行结果。如果 timeout 不是 None 并且在 timeout 秒内仍然没有执行完得到结果,则抛出 multiprocessing.TimeoutError 异常。如果远程调用发生异常,这个异常会通过 get() 重新抛出。

wait([timeout])

阻塞,直到返回结果,或者 timeout 秒后超时。

ready()

用于判断执行状态,是否已经完成。

successful()

判断调用是否已经完成并且未引发异常。 如果还未获得结果则将引发 ValueError

 

监听者及客户端

通常情况下,进程间通过队列或者 Pipe() 返回的 Connection 传递消息。

multiprocessing.connection.deliver_challenge(connectionauthkey)

发送一个随机生成的消息到另一端,并等待回复。

multiprocessing.connection.answer_challenge(connectionauthkey)

接收一条信息,使用 authkey 作为键计算信息摘要,然后将摘要发送回去。

multiprocessing.connection.Client(address[family[authkey]])

尝试在监听者上使用 address 地址初始化一个连接,返回 Connection 

 

class multiprocessing.connection.Listener([address[family[backlog[authkey]]]])

可以监听连接请求,是对于绑定套接字或者 Windows 命名管道的封装。

accept()

接受一个连接并返回一个 Connection 对象,其连接到的监听器对象已绑定套接字或者命名管道。如果已经尝试过认证并且失败了,则会抛出 AuthenticationError 异常。

close()

关闭监听器上的绑定套接字或者命名管道。此函数会在监听器被垃圾回收后自动调用。不过仍然建议显式调用函数关闭。

监听器对象拥有下列只读属性:

address

被监听器对象使用的地址。

last_accepted

最后一个连接所使用的地址。如果没有的话就是 None 

 

multiprocessing.connection.wait(object_listtimeout=None) 方法

一直等待直到 object_list 中某个对象处于就绪状态。返回 object_list 中处于就绪状态的对象。如果 timeout 是一个浮点型,该方法会最多阻塞这么多秒。如果 timeout  None ,则会允许阻塞的事件没有限制。timeout为负数的情况下和为0的情况相同。

对于 Unix Windows ,下列对象都可以出现在 object_list 

 

认证密码

认证密钥是一个 byte 类型的字符串,可以认为是和密码一样的东西,连接建立好后,双方都会要求另一方证明知道认证密钥。(这个证明过程不会通过连接发送密钥)

 

 

日志记录

当前模块也提供了一些对 logging 的支持。注意, logging 模块本身并没有使用进程间共享的锁,所以来自于多个进程的日志可能(具体取决于使用的日志 handler)相互覆盖或者混杂。

 

multiprocessing.get_logger()

返回 multiprocessing 使用的 logger,必要的话会创建一个新的。

 

multiprocessing.log_to_stderr()

此函数会调用 get_logger() 但是会在返回的 logger 上增加一个 handler,将所有输出都使用 '[%(levelname)s/%(processName)s] %(message)s' 的格式发送到 sys.stderr 

 

multiprocessing.dummy 模块

multiprocessing.dummy 复制了 multiprocessing  API,不过是在 threading 模块之上包装了一层。

 

 

 

编程指导

使用 multiprocessing 时,应遵循一些指导原则和习惯用法。

安全导入主模块

确保主模块可以被新启动的Python解释器安全导入而不会引发什么副作用(比如又启动了一个子进程)

例如,使用 spawn  forkserver 启动方式执行下面的模块,会引发 RuntimeError 异常而失败。

from multiprocessing import Process

def foo():
   
print('hello')

p = Process(target=foo)
p
.start()

应该通过下面的方法使用 if __name__ == '__main__': ,从而保护程序"入口点":

from multiprocessing import Process, freeze_support, set_start_method

def foo():
   
print('hello')

if __name__ == '__main__':
    freeze_support()
    set_start_method(
'spawn')
    p
= Process(target=foo)
    p
.start()

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值