我应该如何以及何时使用on.exit? [英] How and when should I use on.exit?

查看:218
本文介绍了我应该如何以及何时使用on.exit?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

on.exit 在函数退出时调用代码,但是应该如何以及何时调用我用吗?

on.exit calls code when a function exits, but how and when should I use it?

推荐答案

on.exit的优点在于,无论是否抛出错误,该函数退出时都会被调用..这意味着它的主要用途是在发生危险行为后进行清理.在这种情况下,冒险通常意味着访问R之外的资源(因此不能保证可以正常工作).常见的示例包括连接到数据库或文件(即使出现错误也必须在完成后关闭连接),或将绘图保存到文件(此后必须关闭图形设备).

The advantage of on.exit is that is gets called when the function exits, regardless of whether an error was thrown. This means that its main use is for cleaning up after risky behaviour. Risky, in this context, usually means accessing resources outside of R (that consequently cannot be guaranteed to work). Common examples include connecting to databases or file (where the connection must be closed when you are finished, even if there was an error), or saving a plot to a file (where the graphics device must be closed afterwards).

您还可以将on.exit用于具有副作用的低风险行为,例如设置工作目录.

You can also use on.exit for low-risk behaviour with a side effect, such as setting a working directory.

withr 程序包包含许多with_*函数,这些函数可更改设置,运行某些代码,然后改回设置.这些功能也出现在 devtools 包中.

The withr package contains many with_* functions that change a setting, run some code, then change the setting back. These functions also appear in the devtools package.

later 包中找到了另一种语法,其中deferon.exitscope_*函数的作用类似于前面提到的软件包中的with_*函数.

An alternate syntax is found in the later package where defer is a convenience wrapper to on.exit, and scope_* functions work like the with_* functions in the previously mentioned packages.

在此示例中,sqlite_get_query连接到sqlite数据库,确保 在查询运行后,连接总是关闭. cookies 数据库要求您在计算机上安装了Firefox,并且您可能 需要调整路径以查找cookie文件.

In this example, sqlite_get_query connects to an sqlite database, ensuring that the connection always gets closed after the query has run. The cookies database requires that you have firefox installed on your machine, and you may need to adjust the path to find the cookies file.

library(RSQLite)
sqlite_get_query <- function(db, sql)
{
  conn <- dbConnect(RSQLite::SQLite(), db)
  on.exit(dbDisconnect(conn))
  dbGetQuery(conn, sql)
}

cookies <- dir(
  file.path(Sys.getenv("APPDATA"), "Mozilla", "Firefox"), 
  recursive  = TRUE, 
  pattern    = "cookies.sqlite$",
  full.names = TRUE
)[1]

sqlite_get_query(
  cookies, 
  "SELECT `baseDomain`, `name`, `value` FROM moz_cookies LIMIT 20"
)


文件连接

在此示例中,read_chars包装readChars,确保连接 读取完成后,文件始终关闭.


File connections

In this example, read_chars wraps readChars, ensuring that the connection to the file is always closed after reading is finished.

read_chars <- function(file_name)
{
  conn <- file(file_name, "r")
  on.exit(close(conn))
  readChar(conn, file.info(file_name)$size)
}

tmp <- tempfile()
cat(letters, file = tmp, sep = "")
read_chars(tmp)


临时文件

下面的示例改编自 CodeDepends ,该示例使用临时文件来保存会话历史记录.函数返回后就不需要此临时文件,因此将其删除.


Temporary files

The following example adapted from CodeDepends uses a temporary file to save the session history. This temporary file is not needed once the function returns so it is removed.

history_lines <- function()
{
  f <- tempfile()
  on.exit(unlink(f))
  savehistory(f)
  readLines(f, encoding = "UTF-8")
}


保存基本图形

在此示例中,my_plot是使用基数创建图的函数 图形. save_base_plot接受一个函数和一个文件以将其保存到 on.exit确保图形设备始终处于关闭状态.


Saving base graphics

In this example, my_plot is a function that creates a plot using base graphics. save_base_plot accepts a function and a file to save it to, using on.exit to ensure that the graphics device is always closed.

my_plot <- function()
{
  with(cars, plot(speed, dist))
}

save_base_plot <- function(plot_fn, file)
{
  png(file)
  on.exit(dev.off())
  plot_fn()
}

save_base_plot(my_plot, "testcars.png")


临时设置基本图形选项

在此示例中,plot_with_big_margins调用plot,覆盖全局mar gin


Setting base graphics options temporarily

In this example, plot_with_big_margins calls plot, overriding the global margin parameter, using on.exit to reset it after the plot is completed.

plot_with_big_margins <- function(...)
{
  old_pars <- par(mar = c(10, 9, 9, 7))  
  on.exit(par(old_pars))
  plot(...)
}

plot_with_big_margins(with(cars, speed, dist))

withr/devtools等效项: with_par

withr/devtools equivalent: with_par

在此示例中,create_data_frame是创建data.frame的函数. create_data_frame确保创建的对象不包含显式因素.

In this example, create_data_frame is a function that creates a data.frame. create_data_frame ensures that the created object doesn't contain explicit factors.

create_data_frame <- function(){
  op <- options(stringsAsFactors = FALSE)
  on.exit(options(op))

  data.frame(x=1:10)
}

withr/devtools等效项: with_options
later等效项:scope_options

withr/devtools equivalent: with_options
later equivalent: scope_options

  • 设置工作目录(withr::with_dirlater::scope_dir)
  • 设置语言环境组件(withr::with_locale)
  • 设置环境变量(withr::with_envvarslater::scope_env_var)
  • 设置库路径(withr::with_libpaths)
  • 使用接收器重定向输出
  • 临时加载软件包(withr::with_packagewithr::with_namespace)
  • Setting the working directory (withr::with_dir, later::scope_dir)
  • Setting locale components (withr::with_locale)
  • Setting environment variables (withr::with_envvars, later::scope_env_var)
  • Setting library paths (withr::with_libpaths)
  • Redirecting output with a sink
  • Temporarily loading a package (withr::with_package, withr::with_namespace)

这篇关于我应该如何以及何时使用on.exit?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆