最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

r - How to write warnings and error generated in rendering rmarkdown file in a log file? - Stack Overflow

programmeradmin0浏览0评论

I have a rmarkdown setup to take input of csv data and saves results in xlsx and word file. I am rendering the rmd file within trycatch to save the warnings created within in a log file. But looks like warning messages are not generated only. I also have added this line to make sure i have a warning message : warning("This is a test warning.")

The code i am using is:

log.path <- paste0(path, "/", "logfile.txt") # Update this to your desired log file path
print(paste("Log file path:", log.path))

# Check if the directory exists, create it if it doesn't
log_dir <- dirname(log.path)
if (!dir.exists(log_dir)) {
  dir.create(log_dir, recursive = TRUE)
  print(paste("Created directory:", log_dir))
}

# Set the warning option to capture warnings
options(warn = 1)  # Set to 1 to turn warnings into messages

# Use tryCatch to handle both warnings and errors
tryCatch(
  {
    # Render the R Markdown file
    rmarkdown::render(
      "Data_cleaning.rmd", 
      params = params_list,
      output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
    )
    
    # Log a message indicating successful rendering
    cat("Data cleaning summary rendered successfully.\n", file = log.path, append = TRUE)
    
  },
  
  error = function(err.msg) {
    # Add error message to the error log file
    write(toString(err.msg), log.path, append=TRUE)
    # err.msg <- cond$message  # Capture the error message
    # cat(paste("Error:", err.msg, "\n"), file = log.path, append = TRUE)
  },
  
  warning = function(warningcondition){   
    # Add warning message to the log file 
    write(toString(warningcondition), log.path, append=TRUE)
  }
)

# Capture warnings separately
options(warn = 1)  # Ensure warnings are treated as messages
withCallingHandlers(
  {
    # Render the R Markdown file again to capture warnings
    rmarkdown::render(
      "Data_cleaning.rmd",  
      params = params_list,
      output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
    )
  },
  
  warning = function(cond) {
    # Capture the warning message
    warning.msg <- cond$message
    cat(paste("Warning:", warning.msg, "\n"), file = log.path, append = TRUE)
    invokeRestart("muffleWarning")  # Prevent the warning from being printed to the console
  }
)

# Reset warning option to default after tryCatch
options(warn = 0)

Is there any better way to write warnings and errors to an external file while running rmarkdown

I tried many ways to write the warnings to a file. but the messages are not generating when i am rendering rmarkdown. Is there any thing i am missing in this approach?

I have a rmarkdown setup to take input of csv data and saves results in xlsx and word file. I am rendering the rmd file within trycatch to save the warnings created within in a log file. But looks like warning messages are not generated only. I also have added this line to make sure i have a warning message : warning("This is a test warning.")

The code i am using is:

log.path <- paste0(path, "/", "logfile.txt") # Update this to your desired log file path
print(paste("Log file path:", log.path))

# Check if the directory exists, create it if it doesn't
log_dir <- dirname(log.path)
if (!dir.exists(log_dir)) {
  dir.create(log_dir, recursive = TRUE)
  print(paste("Created directory:", log_dir))
}

# Set the warning option to capture warnings
options(warn = 1)  # Set to 1 to turn warnings into messages

# Use tryCatch to handle both warnings and errors
tryCatch(
  {
    # Render the R Markdown file
    rmarkdown::render(
      "Data_cleaning.rmd", 
      params = params_list,
      output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
    )
    
    # Log a message indicating successful rendering
    cat("Data cleaning summary rendered successfully.\n", file = log.path, append = TRUE)
    
  },
  
  error = function(err.msg) {
    # Add error message to the error log file
    write(toString(err.msg), log.path, append=TRUE)
    # err.msg <- cond$message  # Capture the error message
    # cat(paste("Error:", err.msg, "\n"), file = log.path, append = TRUE)
  },
  
  warning = function(warningcondition){   
    # Add warning message to the log file 
    write(toString(warningcondition), log.path, append=TRUE)
  }
)

# Capture warnings separately
options(warn = 1)  # Ensure warnings are treated as messages
withCallingHandlers(
  {
    # Render the R Markdown file again to capture warnings
    rmarkdown::render(
      "Data_cleaning.rmd",  
      params = params_list,
      output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
    )
  },
  
  warning = function(cond) {
    # Capture the warning message
    warning.msg <- cond$message
    cat(paste("Warning:", warning.msg, "\n"), file = log.path, append = TRUE)
    invokeRestart("muffleWarning")  # Prevent the warning from being printed to the console
  }
)

# Reset warning option to default after tryCatch
options(warn = 0)

Is there any better way to write warnings and errors to an external file while running rmarkdown

I tried many ways to write the warnings to a file. but the messages are not generating when i am rendering rmarkdown. Is there any thing i am missing in this approach?

Share Improve this question asked Mar 18 at 6:35 Sandhya GhildiyalSandhya Ghildiyal 3332 silver badges13 bronze badges 1
  • inside your .rmd you can place a hookset that cats warnings / errors knitr::knit_hooks$set( warning = function(x)...cat(x, file = "logfile.txt") or maybe use R's classic sink: sink("out_logfile.txt", append = TRUE, type = "output") and sink("out_logfile.txt", append = TRUE, type = "warning") ... tryCatch( { rmarkdown::render( error = \(e) cat(paste("ERROR:", e$message, "\n")) same for warnings and close your sinks sink() sink(). Did something similar before, maybe it helps. – Tim G Commented Mar 24 at 17:08
Add a comment  | 

1 Answer 1

Reset to default 2 +25

Here is an approach using knitr output hooks as @Tim G suggests in conjunction with the {logger} package.

For each message class (i.e., message, warnings, or errors) we can:

  1. get a copy of the corresponding old knitr hook so that we might call it in our new hook
  2. make a log file in which to place any corresponding class messages
  3. set the new knitr hook to log any class message to the file and then call the old hook

Note, to set the global knitr chunk option error = TRUE to continue knitting on error.

---
title: "Untitled"
output: html_document
date: "2025-03-26"
---

```{r setup, include=FALSE}
# set global chunk options
## echo = TRUE to show code in output
## error = TRUE to continue on errors
knitr::opts_chunk$set(echo = TRUE, error = TRUE)

library(logger)

local({
  # messages
  message_hook_old <- knitr::knit_hooks$get("message")
  message_out <- "message.txt"
  log_appender(appender_file(message_out), "message")
  knitr::knit_hooks$set(message = function(x, options) {
    log_info(x, namespace = "message")
    message_hook_old(x, options)
  })
  
  # warnings
  warning_hook_old <- knitr::knit_hooks$get("warning")
  warning_out <- "warning.txt"
  log_appender(appender_file(warning_out), "warning")
  knitr::knit_hooks$set(warning = function(x, options) {
    log_warn(x, namespace = "warning")
    warning_hook_old(x, options)
  })
  
  # errors
  error_hook_old <- knitr::knit_hooks$get("error")
  error_out <- "error.txt"
  log_appender(appender_file(error_out), "error")
  knitr::knit_hooks$set(error = function(x, options) {
    log_error(x, namespace = "error")
    error_hook_old(x, options)
  })
})
```

```{r}
message("This is a message.")
```

```{r}
warning("This is a warning.")
```

```{r}
stop("This is an error.")
```

Results

HTML

message.txt

INFO [2025-03-26 15:55:17] ## This is a message.

warning.txt

WARN [2025-03-26 15:55:17] ## Warning: This is a warning.

error.txt

ERROR [2025-03-26 15:55:17] ## Error: This is an error.
发布评论

评论列表(0)

  1. 暂无评论