提问人:Cblopez 提问时间:5/28/2020 最后编辑:kadambCblopez 更新时间:6/5/2020 访问量:109
在特定进程中抑制 stdout
Supressing stdout in particular process
问:
我有一个执行两个主要任务的 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()
语句,因为程序的另一个例程在主进程上调用该函数,并且它需要这些 print 语句。
我还注意到,我可以使用布尔标志来指示是否应该执行打印,但我希望有人能给我一个更好的方法。
谢谢!
答:
0赞
teki
6/1/2020
#1
你必须在分叉之后在进程内完成。这有点粗糙,但似乎正在起作用:
#!/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")
思路来源: 如何使用脚本将 stdout 重定向到文件和控制台?
评论
0赞
Cblopez
6/1/2020
这似乎奏效了。虽然不需要该对象,但如果您这样做,它工作得很好,但是主进程如何更改其所有子进程 STDOUT(这很好,因为它应该像那样工作),但是修改他的 STDOUT 的子进程不会更改其他进程 STDOUT(这也很好,但每个都指向同一个对象!模块是否在桌子底下进行这些小更改?sys.stdout = None
sys.stdout = something
sys.stdout
multiprocessing
2赞
kmaork
6/5/2020
#2
我试图通过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
评论
0赞
Cblopez
6/5/2020
谢谢!这个解释就是我一直在寻找的。os.fork
评论