使用 capture.output 捕获警告
capture warnings with capture.output
我在使用 capture.output()
时遇到问题,我不明白为什么,因为它在大多数情况下只是 sink()
.
的包装器
使用 sink()
考虑这个简单的例子:
foo = function() warning("foo")
f = file()
sink(f, type = "message")
foo()
readLines(f)
## [1] "Warning message:" "In foo() : foo"
close(f)
这按预期工作。但是,capture.output()
不会:
f = file()
capture.output(foo(), file = f, type = "message")
## Warning message:
## In foo() : foo
readLines(f)
## character(0)
close(f)
capture.output()
是否适用于消息:
bar = function() message("bar")
f = file()
capture.output(bar(), file = f, type = "message")
readLines(f)
## [1] "bar"
close(f)
但是根据文档,应该捕获消息和警告:
Messages sent to stderr()
(including those from message
, warning
and stop
) are captured by type = "message"
.
我在这里错过了什么?
@MrFlick 的评论指出了一个潜在的解决方案,前提是您可以控制传递给 warning()
的参数。如果您使用参数 immediate. = TRUE
,则 capture.output()
可以检索警告消息。
baz = function() warning("baz", immediate. = TRUE)
res = capture.output(baz(), type = "message")
print(res)
## [1] "Warning in baz() : baz"
编辑
或者,@user2554330 指出您可以使用 options(warn = 1)
在全局范围内立即打印警告。
oldopt = getOption("warn")
options(warn = 1)
res = capture.output(foo(), type = "message")
print(res)
## [1] "Warning in foo() : foo"
options(warn = oldopt)
编辑 2
为了完整起见,我认为使用 withCallingHandlers
指出这种替代方法会很有帮助,它不需要对选项进行任何更改,并且可能是一种更简洁的解决方案,具体取决于应用程序。考虑这个嵌套警告的例子:
foo = function() {
warning("foo")
bar()
}
bar = function() {
warning("bar")
baz()
}
baz = function() {
warning("baz")
TRUE
}
# create a container to hold warning messages
logs = vector("character")
# function to capture warning messages
log_fun = function(w) logs <<- append(logs, w$message)
# function call with message capturing
withCallingHandlers(foo(), warning = log_fun)
## [1] TRUE
## Warning messages:
## 1: In foo() : foo
## 2: In bar() : bar
## 3: In baz() : baz
print(logs)
## [1] "foo" "bar" "baz"
请注意 withCallingHandlers
允许您为不同的信号条件指定不同的行为,例如warnings
和 messages
可以存储在单独的变量中。
我在使用 capture.output()
时遇到问题,我不明白为什么,因为它在大多数情况下只是 sink()
.
使用 sink()
考虑这个简单的例子:
foo = function() warning("foo")
f = file()
sink(f, type = "message")
foo()
readLines(f)
## [1] "Warning message:" "In foo() : foo"
close(f)
这按预期工作。但是,capture.output()
不会:
f = file()
capture.output(foo(), file = f, type = "message")
## Warning message:
## In foo() : foo
readLines(f)
## character(0)
close(f)
capture.output()
是否适用于消息:
bar = function() message("bar")
f = file()
capture.output(bar(), file = f, type = "message")
readLines(f)
## [1] "bar"
close(f)
但是根据文档,应该捕获消息和警告:
Messages sent to
stderr()
(including those frommessage
,warning
andstop
) are captured bytype = "message"
.
我在这里错过了什么?
@MrFlick 的评论指出了一个潜在的解决方案,前提是您可以控制传递给 warning()
的参数。如果您使用参数 immediate. = TRUE
,则 capture.output()
可以检索警告消息。
baz = function() warning("baz", immediate. = TRUE)
res = capture.output(baz(), type = "message")
print(res)
## [1] "Warning in baz() : baz"
编辑
或者,@user2554330 指出您可以使用 options(warn = 1)
在全局范围内立即打印警告。
oldopt = getOption("warn")
options(warn = 1)
res = capture.output(foo(), type = "message")
print(res)
## [1] "Warning in foo() : foo"
options(warn = oldopt)
编辑 2
为了完整起见,我认为使用 withCallingHandlers
指出这种替代方法会很有帮助,它不需要对选项进行任何更改,并且可能是一种更简洁的解决方案,具体取决于应用程序。考虑这个嵌套警告的例子:
foo = function() {
warning("foo")
bar()
}
bar = function() {
warning("bar")
baz()
}
baz = function() {
warning("baz")
TRUE
}
# create a container to hold warning messages
logs = vector("character")
# function to capture warning messages
log_fun = function(w) logs <<- append(logs, w$message)
# function call with message capturing
withCallingHandlers(foo(), warning = log_fun)
## [1] TRUE
## Warning messages:
## 1: In foo() : foo
## 2: In bar() : bar
## 3: In baz() : baz
print(logs)
## [1] "foo" "bar" "baz"
请注意 withCallingHandlers
允许您为不同的信号条件指定不同的行为,例如warnings
和 messages
可以存储在单独的变量中。