Cblopez
Cblopez

Reputation: 576

Supressing stdout in particular process

I have a Python script that executes two main tasks:

My question is: Is there any way of muting the stdout from that particular process without affecting the main process? I've tried to change it through sys.stdout, but it affects every single process and the main process (every instance of the program points to the same object):

>>> import multiprocessing
>>> import sys
>>> def a():
...     print('{} - {}'.format(sys.stdout, id(sys.stdout)))
... 
>>> for i in range(5):
...     multiprocessing.Process(target=a).start()
... 
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232
>>> <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232

>>> a()
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> - 140230387621232

It is not possible to delete all print() statements from the function being executed by the process, since another routine of the program calls that function on the main process and it needs those print statements.

I also noticed that I could use a boolean flag to indicate whether the print should be executed or not, but I was hoping that anyone could give me a better approach.

Thank you very much!

Upvotes: 0

Views: 118

Answers (2)

kmaork
kmaork

Reputation: 6012

I've tried to change it through sys.stdout, but it affects every single process and the main process (every instance of the program points to the same object)

The solution you offered here actually works. Try running this simple example:

def a(no_stdout):
    if no_stdout:
        sys.stdout = None
    print(id(sys.stdout))

multiprocessing.Process(target=a, args=(False,)).start() # Outputs the id
multiprocessing.Process(target=a, args=(True,)).start()  # Outputs nothing

The reason that all the processes in your example print the same id is that multiprocessing.Process uses os.fork on your platform. When forking, all the process's memory remains identical (and even stays at the same physical address until it is modified by the child process). So although the addresses are the same, they each refer to a different sys.stdout object in each of the processes' memory.

Upvotes: 2

teki
teki

Reputation: 2062

You have to do it inside the process, after fork. This is a bit crude, but seems to be working:

#!/usr/bin/env python3

import multiprocessing
import sys

class SinkLogger(object):
    def __init__(self):
        pass

    def write(self, message):
        pass

    def flush(self):
        pass  

def a(i):
    if (i % 2 == 1):
        sys.stdout = SinkLogger()
    print('{} - {} - {}'.format(i, sys.stdout, id(sys.stdout)))

for i in range(5):
    multiprocessing.Process(target=a, args=(i,)).start()

print("done")

Source of the idea: How to redirect stdout to both file and console with scripting?

Upvotes: 0

Related Questions