Цикл прерывания с помощью системной команды

Я использую Rscript все больше и больше, где обычно использовал скрипты bash. Одно небольшое раздражение состоит в том, что многие из этих сценариев пересекаются с каким-то вызовом system(), который практически не оставляет времени для R, чтобы поймать мой элемент управления-c, если я попытаюсь его прервать. Вместо этого он просто прерывает выполняемую системную команду и переходит к следующей итерации цикла. Например, когда я пытаюсь прервать следующее, удерживая control-c, он все равно пропускает все итерации:

for(i in 1:10) {
  cat(i)
  system('sleep 3')
}

До сих пор я всегда просто взламывал это, вставляя небольшую паузу в каждый цикл, например

for(i in 1:10) {
  Sys.sleep(0.25)
  cat(i)
  system('sleep 3')
}

который позволит мне прервать внутри итерации или два, если я удерживаю control-c, но мне интересно, есть ли более эффективный способ выполнить это поведение?

Ответы

Ответ 1

Джон, я не уверен, поможет ли это, но из исследования setTimeLimit я узнал, что он может остановить выполнение, когда пользователь может выполнить прерывание, например, Ctrl-C. См. этот вопрос для некоторых ссылок.

В частности, обратные вызовы могут быть способом, и я проверил addTaskCallback и это руководство по developer.r-project.org.

Вот еще четыре предложения:

  • Хотя это взломать совсем другой подход, я должен вызывать два сеанса R, один - мастер-сеанс, а другой просто существует для выполнения команд оболочки, переданных мастер-сессией, которая только ждет подтверждения, что работа была выполнена до начала следующего.

  • Если вы можете использовать foreach вместо for (либо параллельно, через% dopar%, либо serial% do%, а не% dopar% или w/только 1 зарегистрированный рабочий), это может быть более восприимчивым к прерываниям, так как это может быть эквивалентно первому предложению (поскольку оно вилки R).

  • Если вы можете получить код выхода для внешней команды, это может быть передано в условный цикл. Этот предыдущий Q & A будет полезен в этом отношении.

  • Если вы хотите, чтобы все было запущено в bash script, тогда R мог просто написать один длинный script (т.е. вывести строку или ряд строк в файл). Это может быть выполнено, и прерывание гарантировано не влияет на цикл, поскольку вы развернули цикл. Кроме того, вы можете писать циклы в bash. Вот примеры. Лично мне нравится применять команды к файлам с помощью find (например, find .... -exec doStuff {} ';') или как входы через backquotes. К сожалению, я не могу легко дать хорошо отформатированный код на SO, так как он вводит backquotes внутри backquotes... См. Эту страницу для примеров Таким образом, может случиться так, что у вас может быть одна команда, нет цикла и применить функцию ко всем файлам, удовлетворяющим определенному набору критериев. Использование подстановки команд через backquotes - очень удобный трюк для пользователя bash.

Ответ 2

Вы должны проверить, что каждый вызов system() имеет ненулевой статус выхода. Если есть непредвиденная ошибка, ваша программа должна stop(), или вы можете получить неожиданные результаты. Вызываемые вами программы должны возвращать ненулевой статус выхода при уничтожении с помощью Ctrl + C, а если это не так, это ошибка или недостаток этих программ.