问题
I have a function fun
that relies on an external function external
(i.e., from some package). How can I collect all the warnings that come out of external
in a character vector?
This is a minimal setup:
# External function from another package.
external <- function() {
warning("warning from external...")
}
# Function meant to capture the warnings.
fun <- function() {
# Create variable to store the warnings.
warns <- vector("character")
# Create connection for the sink.
connection <- textConnection("warns", "wr", local = TRUE)
# Start collecting.
sink(connection, type = "message")
# Call external function and produce a warning.
external()
# Reset the sink.
sink(type = "message")
# Close the connection.
close(connection)
return(warns)
}
The output, however looks like this:
x <- fun()
# Warning message:
# In external() : warning from external...
print(x)
# character(0)
I am not interested in suppressWarnings
, but rather to log these warnings. When I use sink
outside of a function it seems to work, just as indicated in this answer.
回答1:
You can use tryCatch
for this:
fun <- function() {
tryCatch(external(), warning = function(my_warn) my_warn$message)
}
x <-fun()
x
# [1] "warning from external..."
回答2:
You can try evaluate()
function from evaluate
package, if you want to store warnings in a character vector:
external <- function() {
warning("warning from external...")
}
# Function meant to capture the warnings.
fun <- function() {
#some operation
x=1+2;
warnings_ls = evaluate::evaluate(external())
return(list(value=x,warn=warnings_ls))
}
x <- fun()
> a$warn[[1]]$src
[1] "warning from external..."
> a$value
[1] 3
回答3:
Supplementing the answers above, the warn
option (see ?options
) says:
sets the handling of warning messages. If
warn
is negative all warnings are ignored. Ifwarn
is zero (the default) warnings are stored until the top–level function returns. If 10 or fewer warnings were signalled they will be printed otherwise a message saying how many were signalled. An object calledlast.warning
is created and can be printed through the functionwarnings
. If warn is one, warnings are printed as they occur. Ifwarn
is two or larger all warnings are turned into errors.
In that sense, setting options(warn = 1)
before the sink
makes it possible for the warning messages can be captured. The warn
can be reverted to default after resetting the sink
(i.e., options(warn = 0)
). Then, fun
would look something like:
fun <- function() {
# Print warnings as they occur.
options(warn = 1)
# Create variable to store the warnings.
warns <- vector("character")
# Create connection for the sink.
connection <- textConnection("warns", "wr", local = TRUE)
# Start collecting.
sink(connection, type = "message")
# Call external function and produce a warning.
external()
# Reset the sink.
sink(type = "message")
# Close the connection.
close(connection)
# Restore default warning behavior.
options(warn = 0)
return(warns)
}
With the following output:
fun()
# [1] "Warning in external() : warning from external..."
来源:https://stackoverflow.com/questions/57657901/how-to-use-the-sink-function-within-another-function-in-r