Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a Python multiprocessing daemon process not printing to standard output?

I have been experimenting with multiprocessing, and running into a mindblock with daemons.

I have one daemon and one non-daemon process, the daemon emitting output every one second indefinitely, while the non-daemon prints output immediately upon start, sleeps for 3 seconds, then prints again and returns.

The problem is, the expected output from the daemon process doesn't show up at all.

Reviewing past SO questions on daemons, the common issues appear to be either the other processes ending before the daemon, or the stdout requiring flushing to show output. Both have (I think) been addressed, however I continue to only see printed output from non-daemonic processes.

The code:

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()

Expected Output:

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

What actually gets produced:

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

Any advice on why this is happening would be truly appreciated.

like image 907
zehnpaard Avatar asked Dec 31 '14 11:12

zehnpaard


1 Answers

You can get a clearer picture of the order of events by turning on logging by placing

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

after the other import statements. Then your program will yield something like:

[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

Thus, the main starts shutting down first, then it terminates Process-1, the daemon process. That's why you do not see any more beeps while Process-2 continues.

like image 139
unutbu Avatar answered Oct 28 '22 11:10

unutbu