我正在努力理解多处理。我的实际应用程序是在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
与我期望得到的输出:
q has 0 elements
qsize in add_to_q is 2
q has 2 elements
Hello
q has 1 elements
到目前为止,我已经尝试使用multiprocessing.Queue
和queue.Queue
。我也在使用和不使用Process.join()
的情况下对此进行了测试。
如果我在不使用multiprocessing
的情况下运行相同的程序,我会得到上面显示的预期输出。
我在这里做错了什么?
编辑:
Process.run()
给了我预期的输出,但它也在运行时阻塞了主进程,这不是我想做的
我的理解是Process.run()
在调用进程(在我的情况下是主进程(的上下文中运行创建的进程,这意味着它与调用同一函数的主进程没有什么不同。
我仍然不明白为什么我的队列行为没有像预期的那样工作
我已经发现了问题的根源,我将在这里记录它以备将来搜索,但我仍然想知道是否有标准的解决方案可以在模块之间创建全局队列,这样我就可以接受任何其他答案/评论。
当我将以下内容添加到我的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)>
看起来我正在为我创建的每个进程创建单独的Queue对象,这当然可以解释为什么它们没有按预期进行交互。
这个问题有一个评论,指出
共享队列需要源自主流程,然后将其传递给其所有子流程。
尽管如此,我仍然想知道是否有一种有效的方法可以在模块之间共享全局队列,而不必在方法之间传递。