В R я зацикливаюсь на векторе объектов и применяю одни и те же команды на каждой итерации. Как (i) остановить итерацию, которая занимает слишком много времени, (ii) напечатать сообщение об ошибке / предупреждение и (iii) перейти к следующей итерации?
Например, допустим, у меня есть вектор, содержащий 3 периода времени, и я делаю R спящих для этих периодов, применяя ограничение по времени 5 секунд.
Если итерация цикла for занимает более 5 секунд (вторая из векторов здесь), она должна остановиться на (около) 5 секунд и продолжить работу.
Моя проблема с приведенными ниже кодами состоит в том, что, если итерация занимает слишком много времени, R не останавливается, а печатает сообщение об ошибке только после завершения итерации, а не прямо в срок.
vec <- c(2, 12, 3)
# using base R 'setTimeLimit' function
for(i in 1:length(vec)){
cat(". Sleeping", vec[i], "seconds\n")
tryCatch(
{
system.time(
local(
{
setTimeLimit(elapsed = 5, transient = TRUE)
Sys.sleep(vec[i])
}
)
)
},
error=function(e){cat(conditionMessage(e), "\n")}
)
}
# using R.utils 'withTimeout' function
library(R.utils)
for(i in 1:length(vec)){
cat(". Sleeping", vec[i], "seconds\n")
# first 'tryCatch' if error NOT caused by a timeout
tryCatch(
# second 'tryCatch' if error caused by a timeout
tryCatch(
withTimeout(
Sys.sleep(vec[i]),
timeout=5,
onTimeout="error"
),
TimeoutException = function(ex) cat("Timeout. Skipping.\n")
),
error=function(e){cat(conditionMessage(e), "\n")}
)
}
EDIT
Как упоминалось в комментариях, это решение не работает ни с моим примером.
for(i in 1:length(vec)){
+ tryCatch(
+ expr = {
+ withTimeout({Sys.sleep(vec[i]); cat(". Sleeping ", vec[i], " seconds\n")},
+ timeout = 5)
+ },
+ TimeoutException = function(ex) cat("Timeout. Skipping.\n")
+ )
+ }
Выводит:
. Sleeping 2 seconds
Timeout. Skipping. # this message shows up after 12 seconds anyway (I am trying to stop it after timeout = 5s here)
. Sleeping 3 seconds
РЕДАКТИРОВАТЬ 2
Мой пример использования функции Sys.sleep
не работает с withTimeout
.
С R.Utils
руководство:
(*) Обратите внимание, что в Unix и macOS Sys.sleep (время) будет сигнализировать об истечении времени ожидания
ошибка только после истечения времени, независимо от предела времени ожидания (<
время).
Взяв другой пример, сообщение SO, упомянутое в комментариях ниже, на самом деле работает.
library(R.utils)
vec <- c(1e+02, 1e+06, 1e+04)
# the second element of the vector takes some time to run
foo <- function(i){
for(j in 1:i){
invisible(capture.output(print(j)))
}
}
# checking that the second element will take a long time (15 seconds)
system.time(foo(vec[1]))
# user system elapsed
# 0.002 0.001 0.001
system.time(foo(vec[2]))
# user system elapsed
# 11.557 3.157 15.543
system.time(foo(vec[3]))
# user system elapsed
# 0.109 0.031 0.148
for(k in vec){
tryCatch(
{
system.time(withTimeout(
{cat("... Processing ", k, " times...\n\n"); invisible(capture.output(foo(k)))},
timeout = 5
))
},
TimeoutException = function(ex) cat("Timeout. Skipping.\n\n")
)
}
#... Processing 100 times...
#
#... Processing 1e+06 times...
#
#Timing stopped at: 4.993 0.029 5.022 # it stops at timeout = 5s
#Timeout. Skipping.
#
#... Processing 10000 times...