[英]Do I need to pass multiprocessing queues to the process?
以下多处理示例可在我的Ubuntu计算机上使用。 它开始一个过程,通过一个队列发送参数,并通过另一个队列接收计算结果:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import multiprocessing
import Queue
running = multiprocessing.Value('i', 1)
request = multiprocessing.Queue(1)
response = multiprocessing.Queue(1)
def worker():
while running.value:
try:
param = request.get(timeout=0.1)
except Queue.Empty:
# To check running flag.
continue
# Imagine heavy computation here.
result = param ** 2
response.put_nowait(result)
def main():
process = multiprocessing.Process(target=worker)
process.start()
request.put_nowait(42)
result = response.get()
print('Result', result)
running.value = 0
process.join()
if __name__ == '__main__':
main()
但是,网络上的几个示例似乎通过multiprocessing.Process(target=worker, args=(running, request, response)
传递了工作人员所需的所有对象。出于某种原因(例如平台兼容性multiprocessing.Process(target=worker, args=(running, request, response)
,是否有必要这样做?
人们倾向于遵循多处理编程准则 :
继承比腌制/腌制好
在Windows上,多处理中的许多类型需要可腌制,以便子进程可以使用它们。 但是,通常应该避免使用管道或队列将共享对象发送到其他进程。 相反,您应该安排程序,以便需要访问在其他位置创建的共享资源的进程可以从祖先进程继承该程序。
如果您的实现足够简单,则可以使用全局变量。 但是,在更复杂的情况下,您可能希望避免使用它们,而是希望使用更好的封装。
此外,由于操作系统处理新流程的创建方式,您的实现可能无法在Windows上运行。
Unix使用fork
来复制父进程资源。 因此,子级继承父级打开的文件(在您的情况下为Queue
)。
Windows使用spawn
方法,该方法创建一个“空白”进程,加载一个新的Python解释器,并尝试重新构建运行target
函数所需的最低要求。 新流程很有可能会使用与父流程不同的全新Queue
。 因此,您将发送的数据将永远不会到达子进程。
关于最后一条语句的注释:Python multiprocessing
库试图提供与操作系统无关的体验(我个人不喜欢)。 这意味着由于这种努力,您的代码可能仍可在Windows上运行。
由于fork和spawn之间的实际差异没有得到很好的记录,因此始终建议遵循编程准则,以免发生怪异的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.