【问题标题】:Trying to understand multiprocessing and queues across python modules试图理解跨 python 模块的多处理和队列
【发布时间】:2018-07-25 16:46:52
【问题描述】:

我正在尝试了解多处理。我的实际应用是在 pyqt5 GUI 上实时显示日志消息,但是我在使用队列时遇到了一些问题,所以我做了一个简单的程序来测试它。

我看到的问题是我无法跨 python 模块和跨进程将元素添加到队列。这是我的代码和输出,以及预期的输出。

全局配置文件:

# cfg.py
# Using a config file to import my globals across modules

#import queue
import multiprocessing

# q = queue.Queue()
q = multiprocessing.Queue()

主模块:

# mod1.py

import cfg
import mod2
import multiprocessing

def testq():
    global q
    print("q has {} elements".format(cfg.q.qsize()))

if __name__ == '__main__':
    testq()
    p = multiprocessing.Process(target=mod2.add_to_q)
    p.start()
    p.join()
    testq()
    mod2.pullfromq()
    testq()

二级模块:

# mod2.py

import cfg

def add_to_q():
    cfg.q.put("Hello")
    cfg.q.put("World!")
    print("qsize in add_to_q is {}".format(cfg.q.qsize()))


def pullfromq():
    if not cfg.q.empty():
        msg = cfg.q.get()
        print(msg)

这是我实际从中得到的输出:

q has 0 elements
qsize in add_to_q is 2
q has 0 elements
q has 0 elements

vs 我期望得到的输出:

q has 0 elements
qsize in add_to_q is 2
q has 2 elements
Hello
q has 1 elements

到目前为止,我已尝试同时使用 multiprocessing.Queuequeue.Queue。我也测试了这个有和没有Process.join()

如果我在不使用multiprocessing 的情况下运行相同的程序,我会得到如上所示的预期输出。

我在这里做错了什么?

编辑:

Process.run() 给了我预期的输出,但它也在运行时阻塞了主进程,这不是我想要做的。

我的理解是Process.run()在调用进程(在我的情况下是主进程)的上下文中运行创建的进程,这意味着它与调用相同函数的主进程没有区别。

我仍然不明白为什么我的队列行为没有按预期工作

【问题讨论】:

  • 与其在方法中使用固定队列,不如将队列作为参数传递?它避免了处理全局变量。
  • 通常这将是我的方法,但它需要传递给许多函数,因为我正在使用它来捕获日志消息。我也很好奇这里的意外行为。

标签: python module queue multiprocessing


【解决方案1】:

我已经发现了问题的根源,我将在此处记录它以供将来搜索,但我仍然想知道是否有在模块之间创建全局队列的标准解决方案,所以我会接受任何其他的答案/cmets。

当我将以下内容添加到我的 cfg.py 文件时,我发现了问题。

print("cfg.py is running in process {}".format(multiprocessing.current_process()))

这给了我以下输出:

cfg.py is running in process <_MainProcess(MainProcess, started)>
cfg.py is running in process <_MainProcess(Process-1, started)>
cfg.py is running in process <_MainProcess(Process-2, started)>

似乎我正在为我创建的每个进程创建单独的队列对象,这肯定可以解释为什么它们没有按预期进行交互。

This question 有一条评论指出

一个共享队列需要源自主进程,然后将其传递给它的所有子进程。

说了这么多,我仍然想知道是否有一种有效的方法可以在模块之间共享全局队列,而不必在方法之间传递它。

【讨论】:

    猜你喜欢
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2017-12-11
    • 2014-01-11
    • 1970-01-01
    相关资源
    最近更新 更多