如何使用 `with` 语句来抑制 `sys.stdout` 或 `sys.stderr`?
How to use a `with` statement to suppress `sys.stdout` or `sys.stderr`?
我正在尝试使用 with
语句来单独抑制 sys.stdout
或 sys.stderr
。 我发现了 tutorial 那没用。我正在使用 Python 3.6.4
,我认为该教程是 Python 2
的某个版本。
I looked it up on SO 并发现了一些应用程序不起作用或不适用于这种情况。
这不适用:
无法使任何 with
语句起作用:
Suppress stdout / stderr print from Python functions
这是 fortran 语言:Redirecting FORTRAN (called via F2PY) output in Python
from contextlib import contextmanager
@contextmanager
def suppress_console(file=sys.stdout):
with open(os.devnull, "w") as devnull:
old_file = file
file = devnull
try:
yield
finally:
file = old_file
with suppress_console():
print(1, file=sys.stdout)
# 1
我用的是这样的:
class Suppress:
def __init__(self, *, suppress_stdout=False, suppress_stderr=False):
self.suppress_stdout = suppress_stdout
self.suppress_stderr = suppress_stderr
self.original_stdout = None
self.original_stderr = None
def __enter__(self):
import sys, os
devnull = open(os.devnull, "w")
# Suppress streams
if self.suppress_stdout:
self.original_stdout = sys.stdout
sys.stdout = devnull
if self.suppress_stderr:
self.original_stderr = sys.stderr
sys.stderr = devnull
def __exit__(self, *args, **kwargs):
import sys
# Restore streams
if self.suppress_stdout:
sys.stdout = self.original_stdout
if self.suppress_stderr:
sys.stderr = self.original_stderr
示例:
import sys
print("Before")
with Suppress(suppress_stdout=True):
print("Inside")
print("After")
print("Before", file=sys.stderr)
with Suppress(suppress_stderr=True):
print("Inside", file=sys.stderr)
print("After", file=sys.stderr)
输出:
Before
After
Before
After
备注:
- 为了清洁,我将我的导入放在方法中,但通常这会在模块文件中,导入在顶部。
- 抑制 stderr 是有风险的,尤其是因为我(不是)在
__exit__
方法中处理异常的方式。您可能会考虑设计一个更强大的退出方法。
我用的是下面这个:
from contextlib import redirect_stdout, contextmanager
import os
@contextmanager
def suppress():
with open(os.devnull, "w") as null:
with redirect_stdout(null):
yield
测试:
print("qwer")
with suppress():
print("asdf")
print("ghjk")
# qwer
# ghjk
更新
更好的一个:
from contextlib import redirect_stdout, redirect_stderr, contextmanager, ExitStack
import os
@contextmanager
def suppress(out=True, err=False):
with ExitStack() as stack:
with open(os.devnull, "w") as null:
if out:
stack.enter_context(redirect_stdout(null))
if err:
stack.enter_context(redirect_stderr(null))
yield
我正在尝试使用 with
语句来单独抑制 sys.stdout
或 sys.stderr
。 我发现了 tutorial 那没用。我正在使用 Python 3.6.4
,我认为该教程是 Python 2
的某个版本。
I looked it up on SO 并发现了一些应用程序不起作用或不适用于这种情况。
这不适用:
无法使任何 with
语句起作用:
Suppress stdout / stderr print from Python functions
这是 fortran 语言:Redirecting FORTRAN (called via F2PY) output in Python
from contextlib import contextmanager
@contextmanager
def suppress_console(file=sys.stdout):
with open(os.devnull, "w") as devnull:
old_file = file
file = devnull
try:
yield
finally:
file = old_file
with suppress_console():
print(1, file=sys.stdout)
# 1
我用的是这样的:
class Suppress:
def __init__(self, *, suppress_stdout=False, suppress_stderr=False):
self.suppress_stdout = suppress_stdout
self.suppress_stderr = suppress_stderr
self.original_stdout = None
self.original_stderr = None
def __enter__(self):
import sys, os
devnull = open(os.devnull, "w")
# Suppress streams
if self.suppress_stdout:
self.original_stdout = sys.stdout
sys.stdout = devnull
if self.suppress_stderr:
self.original_stderr = sys.stderr
sys.stderr = devnull
def __exit__(self, *args, **kwargs):
import sys
# Restore streams
if self.suppress_stdout:
sys.stdout = self.original_stdout
if self.suppress_stderr:
sys.stderr = self.original_stderr
示例:
import sys
print("Before")
with Suppress(suppress_stdout=True):
print("Inside")
print("After")
print("Before", file=sys.stderr)
with Suppress(suppress_stderr=True):
print("Inside", file=sys.stderr)
print("After", file=sys.stderr)
输出:
Before After Before After
备注:
- 为了清洁,我将我的导入放在方法中,但通常这会在模块文件中,导入在顶部。
- 抑制 stderr 是有风险的,尤其是因为我(不是)在
__exit__
方法中处理异常的方式。您可能会考虑设计一个更强大的退出方法。
我用的是下面这个:
from contextlib import redirect_stdout, contextmanager
import os
@contextmanager
def suppress():
with open(os.devnull, "w") as null:
with redirect_stdout(null):
yield
测试:
print("qwer")
with suppress():
print("asdf")
print("ghjk")
# qwer
# ghjk
更新
更好的一个:
from contextlib import redirect_stdout, redirect_stderr, contextmanager, ExitStack
import os
@contextmanager
def suppress(out=True, err=False):
with ExitStack() as stack:
with open(os.devnull, "w") as null:
if out:
stack.enter_context(redirect_stdout(null))
if err:
stack.enter_context(redirect_stderr(null))
yield