问题描述
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
包中找到了另一种语法,其中defer
是on.exit
和scope_*
函数的作用类似于前面提到的软件包中的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, ensuringthat the connection always gets closed after the query has run. The cookies
database requires that you have firefox installed on your machine, and you mayneed 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 connectionto 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 basegraphics. save_base_plot
accepts a function and a file to save it to, usingon.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 par
仪表,在绘制完成后使用on.exit
将其重置.
Setting base graphics options temporarily
In this example, plot_with_big_margins
calls plot
, overriding the global mar
gin par
ameter, 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
确保创建的对象不包含显式因素.
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_dir
,later::scope_dir
) - 设置语言环境组件(
withr::with_locale
) - 设置环境变量(
withr::with_envvars
,later::scope_env_var
) - 设置库路径(
withr::with_libpaths
) - 使用接收器重定向输出
- 临时加载软件包(
withr::with_package
,withr::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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!