问题
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
warnis negative all warnings are ignored. Ifwarnis 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.warningis created and can be printed through the functionwarnings. If warn is one, warnings are printed as they occur. Ifwarnis 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