为什么Python多进程守护进程不打印标准输出?

8

我一直在尝试使用多进程技术,并且在守护进程方面遇到了难题。

我有一个守护进程和一个非守护进程,守护进程无限期地每秒发出输出,而非守护进程在启动时立即打印输出,然后睡眠3秒钟,再次打印并返回。

问题是,预期从守护进程中获得的输出根本没有出现。

回顾过去关于守护进程的SO问题,常见问题似乎要么是其他进程在守护进程之前结束,要么是stdout需要刷新才能显示输出。这两个问题(我认为)都已经解决了,但我仍然只看到来自非守护进程的打印输出。

代码:

from multiprocessing import Process, current_process
import sys
import time

def worker():
    """
    Announce that the process has started, sleep 3 seconds
    then announce that the process is ending.
    """
    name = current_process().name
    print name, 'starting...'
    sys.stdout.flush()

    time.sleep(3)
    print name, 'ending...'
    sys.stdout.flush()

    return


def daemon():
    """
    Announce that the process has started, beep, then beep
    once every second
    """
    name = current_process().name
    print name, 'starting...'
    print 'beep...'
    sys.stdout.flush()

    while True:
        time.sleep(1)
        print 'beep...'
        sys.stdout.flush()


if __name__=='__main__':
    d = Process(target=daemon)
    d.daemon = True
    d.start()

    p = Process(target=worker)
    p.daemon = False
    p.start()

期望输出:

Process-1 starting... # Order here may vary
beep...
Process-2 starting...
beep...
beep...
Process-2 ending... #There may or may not be another beep here

实际产出的内容:

Process-2 starting...
Process-2 ending...

任何关于为什么会发生这种情况的建议都将不胜感激。
1个回答

10

通过启用日志记录,您可以更清晰地了解事件发生的顺序,方法是放置

import multiprocessing as mp
logger = mp.log_to_stderr(logging.INFO)

在其他导入语句之后导入这个模块,然后你的程序会输出类似于:

[INFO/Process-1] child process calling self.run()
[INFO/MainProcess] process shutting down
Process-1 starting...
beep...
[INFO/Process-2] child process calling self.run()
[INFO/MainProcess] calling terminate() for daemon Process-1
Process-2 starting...
[INFO/MainProcess] calling join() for process Process-2
Process-2 ending...
[INFO/Process-2] process shutting down
[INFO/Process-2] process exiting with exitcode 0
[INFO/MainProcess] calling join() for process Process-1

因此,主进程首先开始关闭,然后终止进程1,即守护进程。这就是为什么在进程2继续运行时不再听到任何蜂鸣声的原因。


啊,我明白了。当主进程结束时,守护进程会被终止,而不是在所有非守护子进程完成后才终止。这很有道理,非常感谢!我想,在主进程的末尾添加p.join()将使其等待非守护进程完成。 - zehnpaard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接