0

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

  • 从脚本本身执行代码
  • 启动后台进程multiprocessing.Process(target=...)

我的问题是:有没有办法在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()语句,因为程序的另一个例程在主进程上调用该函数并且它需要那些打印语句。

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

非常感谢!

4

2 回答 2

1

我试图通过 sys.stdout 对其进行更改,但它会影响每个进程和主进程(程序的每个实例都指向同一个对象)

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

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每个进程内存中的不同对象。

于 2020-06-04T21:31:09.643 回答
0

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?

于 2020-06-01T12:13:57.563 回答