Установка ограничения по времени для каждой итерации цикла - PullRequest
1 голос
/ 27 марта 2019

В 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...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...