我正在使用一个生成警告的函数,我真的不需要阅读。问题是我想并行运行该函数,并且在这样做时,似乎我无法再抑制警告。考虑这个例子:
import warnings
import numpy as np
from joblib import Parallel, delayed
def test(a, b):
if a * b > 10:
warnings.warn("You are being warned!!")
return(a*b)
ii = np.arange(5)
jj = ii + 1
with warnings.catch_warnings():
warnings.filterwarnings("ignore")
with Parallel(n_jobs=4) as parallel:
result = parallel(delayed(test)(i, j) for i, j in zip(ii, jj))
这仍然会产生警告消息...另请注意,在我的情况下,我无法重写函数
test
,因为它是从另一个包导入的。有什么办法可以不收到警告信息吗?
是的,这很烦人!
默认的
joblib
后端会产生额外的进程,这些进程似乎没有继承使用 warnings.filterwarnings
应用的警告过滤器。但是,您可以使用 PYTHONWARNINGS
环境变量来设置警告过滤器;这将影响所有新生成的进程,这些进程从主进程中继承环境变量。
来自相关文档页面:
警告过滤器由传递到 Python 解释器命令行的
选项和-W
环境变量初始化。解释器将所有提供的条目的参数保存在PYTHONWARNINGS
中,而不进行解释;sys.warnoptions
模块在首次导入时解析这些内容(在将消息打印到warnings
后,无效选项将被忽略)。sys.stderr
各个警告过滤器被指定为一系列用冒号分隔的字段:
action:message:category:module:line
一个单独的页面更详细地描述了每个字段的含义,但基本上:
action
描述如何处理警告;对于你来说,你想要 ignore
抑制消息message
可以是一个字符串,必须与警告消息的开头匹配才能过滤它category
是警告类别,例如FutureWarning
,DeprecationWarning
module
和 line
指发出警告的位置这些字段中的任何一个都可以为空,并且您可以省略尾随分号。
所以,忽略所有
FutureWarning
:
在 Jupyter 笔记本中,您可以执行类似的操作
%env PYTHONWARNINGS=ignore::FutureWarning
os.environ
:
import os
os.environ['PYTHONWARNINGS']='ignore::FutureWarning'
似乎应该有一种方法只为生成的进程设置环境变量,但我不知道
joblib
是否为此公开了API。
您可以尝试以下上下文管理器。
import os
class SuppresedOutput:
'''Context manager for always supressing
output to standard output and error.'''
def __init__(self):
'''Initializer'''
self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)]
self.save_fds = [os.dup(1), os.dup(2)]
def __enter__(self):
'''Context begins.'''
# Assign the null pointers to stdout and stderr
os.dup2(self.null_fds[0], 1)
os.dup2(self.null_fds[1], 2)
def __exit__(self, *args):
'''Context Ends.'''
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0], 1)
os.dup2(self.save_fds[1], 2)
# Close all file descriptors
for fd in self.null_fds + self.save_fds:
os.close(fd)
if __name__ == "__main__":
print("This will be printed")
with SuppresedOutput():
print("This will NOT be printed")
print("This will be printed again")