在特定过程中抑制标准输出

Supressing stdout in particular process

我有一个 Python 脚本执行两个主要任务:

我的问题是:有没有什么方法可以在不影响主进程的情况下从特定进程中屏蔽 stdout?我试图通过 sys.stdout 更改它,但它会影响每个进程和主进程(程序的每个实例都指向同一个对象):

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

无法从进程正在执行的函数中删除所有print()语句,因为程序的另一个例程在主进程上调用该函数它需要那些打印语句。

我还注意到我可以使用一个布尔标志来指示是否应该执行打印,但我希望有人能给我一个更好的方法。

非常感谢!

你必须在 fork 之后在进程内完成。这有点粗糙,但似乎有效:

#!/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")

创意来源:How to redirect stdout to both file and console with scripting?

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)

您在此处提供的解决方案确实有效。试试 运行 这个简单的例子:

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

您示例中的所有进程打印相同 id 的原因是 multiprocessing.Process 在您的平台上使用 os.fork。分叉时,所有进程的内存保持不变(甚至保持在相同的物理地址,直到它被子进程修改)。因此,尽管地址相同,但它们各自引用每个进程内存中的不同 sys.stdout 对象。