Python多处理/线程化代码提前退出
问题描述
我正在尝试创建多个进程,每个进程都调用多个线程。 我正在使用python3.5运行以下代码
该问题的简化示例如下:
import multiprocessing
import time
import threading
class dumb(threading.Thread):
def __init__(self):
super(dumb, self).__init__()
def run(self):
while True:
print("hi")
time.sleep(1)
def test():
for i in range(2):
bar = dumb()
bar.start()
def main():
p = []
for i in range(2):
p.append(multiprocessing.Process(target=test))
for i in p:
i.start()
for i in p:
i.join()
if __name__ == '__main__':
main()
我希望这段代码永远打印"hi",但它只为每个进程中的每个线程打印一次(总共打印4次)。
当我删除多进程时,多线程工作。
当我删除多线程时,多处理工作。
阅读多处理文档后,我认为问题所在的部分: Join的文档声明:"阻塞调用线程,直到其Join()方法被调用的进程终止,或者直到发生可选的超时。"
如果它如我所期望的那样工作,当尝试加入时,Main将永远等待。
我在WHILE循环周围放置了TRY/EXCEPT块,没有看到任何错误。
我尝试向"哑巴"类传递一个队列并传递异常,但队列仍然是空的。
任何有关如何调试它的提示都将不胜感激。我最好的猜测是
线程提前退出(尽管While循环后的打印语句从未命中)
主要退出并终止进程
联接工作正常,但不是我预期的方式?
有什么想法吗?
解决方案
解决方法:新错误已作为http://bugs.python.org/issue18966的副本关闭
唉,没有简单、令人满意的"为什么"的解释。原因是multiprocessing
通过调用os._exit()
而不是正常的sys.exit()
来安排工作进程离开Python。os._exit()
跳过所有"正常"关机处理。跳过的部分是.join()
-非守护进程线程,因此该进程在线程仍在运行时消失。
这至少(根据我的说法)应该被记录下来,或者最好是改变。
同时,您已经知道,解决方法是自己显式.join()
线程。
另一种方式
在Python3.4或更高版本下,您也可以使用multiprocessing
的spawn
的启动方法:
https://docs.python.org/3/library/multiprocessing.html?highlight=spawn#contexts-and-start-methods
这会导致工作进程通过sys.exit(exitcode)
完成,它执行所有正常的关闭处理(包括.join()
运行非后台进程线程)。
spawn
是Windows上唯一可用的Start方法,这解释了为什么我在运行您的原始示例时没有问题。
相关文章