我應該如何使用,何時使用?

[英]How and when should I use on.exit?


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

上。當一個函數退出時,退出調用代碼,但是如何以及何時應該使用它?

1 个解决方案

#1


42  

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).

上的優勢。退出是在函數退出時調用,不管是否拋出錯誤。這意味着它的主要用途是在危險行為之后進行清理。在這種情況下,風險通常意味着訪問R之外的資源(因此不能保證工作)。常見的例子包括連接到數據庫或文件(當您完成時,連接必須被關閉,即使出現錯誤),或者將一個情節保存到一個文件(在此之后,圖形設備必須關閉)。

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

你也可以用on。低風險行為的退出,有副作用,例如設置工作目錄。


Packages that make use of on.exit

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.

withr包包含許多具有更改設置、運行一些代碼、然后更改設置的函數。這些函數也出現在devtools包中。

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.

在后面的包中發現了另一種語法,在這個包中,延遲是一個方便的包裝。exit和scope_*函數像前面提到的包中的with_*函數一樣工作。


Database connections

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.

在本例中,sqlite_get_query連接到一個sqlite數據庫,確保在查詢運行后連接總是被關閉。cookie數據庫要求您的機器上安裝了firefox,您可能需要調整路徑以找到cookie文件。

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"
)

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包裝了readChars,確保在讀取完成后,該文件的連接始終是關閉的。

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)

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.

下面的例子來自CodeDepends,它使用一個臨時文件來保存會話歷史。這個臨時文件在函數返回時不需要,因此它被刪除。

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

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是一個使用基本圖形創建繪圖的函數。save_base_plot接受一個函數和一個文件來保存它,並使用它。退出,以確保圖形設備始終關閉。

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")

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_margin調用plot,覆蓋全局邊界參數,使用on。退出,在情節完成后重新設置。

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 equivalent: with_par

withr / devtools等效:with_par


Setting global options temporarily

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是一個創建數據的函數。create_data_frame確保創建的對象不包含顯式的因素。

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

  data.frame(x=1:10)
}

withr/devtools equivalent: with_options
later equivalent: scope_options

withr/devtools等價:with_options稍后等效:scope_options。


Other examples

  • Setting the working directory (withr::with_dir, later::scope_dir)
  • 設置工作目錄(with_dir:with_dir,稍后::scope_dir)
  • Setting locale components (withr::with_locale)
  • 設置語言環境組件(withr::with_locale)
  • Setting environment variables (withr::with_envvars, later::scope_env_var)
  • 設置環境變量(with_envars,稍后::scope_env_var)
  • Setting library paths (withr::with_libpaths)
  • 設置庫路徑(withr::with_libpaths)
  • Redirecting output with a sink
  • 用接收器重定向輸出。
  • Temporarily loading a package
  • 暫時加載一個包

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/02/03/720b66cc7c81626d710534bb3ff3d7ff.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com