5
votes

Attendez une entrée utilisateur pendant 5 secondes et utilisez une valeur par défaut sinon

Je voudrais donner à l'utilisateur la possibilité de saisir une entrée et d'utiliser une valeur par défaut s'il n'entre rien après 5 secondes.

Voici pour la partie entrée:

input <- readline(prompt="Do something? (y/n): ")

Y a-t-il un moyen de le faire en R?


5 commentaires

? Sys.sleep peut-être?


Humm, d'après ce que je comprends, Sys.sleep peut faire attendre R, mais cela ne forcera pas R à arrêter d'attendre et à poursuivre l'exécution si personne ne répond.


Cela peut être difficile, "De plus, il n'est pas possible d'interrompre / de sortir d'une invite" readline "(par exemple, readline () et readLines ()) en utilisant des délais d'expiration; l'exception de délai d'expiration ne sera pas levée tant que l'utilisateur n'aura pas terminé l'invite (c'est-à-dire après avoir appuyé sur ENTER). " Vous devrez être créatif. rdocumentation.org/ packages / R.utils / versions / 2.7.0‌ / topics /…


Je ne sais pas si vous souhaitez conserver ce texte, mais cela peut être fait avec tcltk2 en utilisant tclAfter


Il me semble que @Chabo a raison, et même tcltk2 :: tclAfter est comme Sys.sleep et ne permet que de retarder l'exécution d'une fonction, pas de forcer R à continuer l'exécution d'une fonction après avoir attendu quelques secondes.


3 Réponses :


-1
votes

Je ne trouve pas le moyen d'ignorer cette interaction dans la console. Quoi qu'il en soit, je laisse une fonction concernant le temps où, si vous appuyez sur Entrée hors du temps afin de sauter l'invite, vous obtiendrez une valeur prédéfinie. J'espère que c'est un moyen de sauvegarder cette interaction avec la console.

#set time in seconds to get an answer from prompt 
#some interaction in console is needed, sorry

Q <- function (x) {
    t0 <- Sys.time() 
    input <- readline(prompt="Do something? (y/n): ")
    tf <- Sys.time()-t0

    if (tf > x){
        input <- "your predefined answer"
    }

    print (tf) #remove if you like
    return (input)
}

Q(5)


0 commentaires

1
votes

Si vous avez une version plus récente de R, vous pouvez essayer la fonction withTimeout du package utils pour encapsuler la fonction readline.

Il est difficile de utiliser la fonction dans la base R appelée setTimeLimit.

Ma tentative de solution buggy suit Cela a fonctionné dans RGui, mais cela a également semblé faire planter R-studio de manière fiable

timed_readline <- function(prompt = '',default,timeout = 10)
{
    inner <- function(timeout)    # wrapped in internal function to stop error being displayed
    {
        setTimeLimit(elapsed=timeout,transient=TRUE)
        a <- readline('')
        setTimeLimit(transient=TRUE)
        return(a)
    }

    cat(prompt)
    b <- default
    try({b <- inner(timeout)},silent=TRUE) 
    return(b)
}

En tant que tel, je ne peux pas recommander ce code, mais il pourrait vous inspirer à quelque chose de réalisable p >


1 commentaires

merci d'avoir pris le temps Aaron, très apprécié. cette approche semble fonctionner correctement avec n'importe quelle autre fonction, mais pas avec readline () malheureusement.



2
votes

Voici comment j'accomplis une invite de fenêtre permettant à l'utilisateur de sélectionner le nombre de threads à démarrer dans un cluster. Il utilise une valeur par défaut, puis il continuera après avoir appuyé sur le bouton OK ou après 5 secondes.

library(tcltk2)

clusterCount = 1

tklist <- list()
tklist <- within(tklist, {
  # define processor input window
  win1 <- tktoplevel()
  rb1 <- tk2radiobutton(win1)
  rb2 <- tk2radiobutton(win1)
  rb3 <- tk2radiobutton(win1)
  rb4 <- tk2radiobutton(win1)
  rbCluster <- tclVar(clusterCount)
  tkconfigure(rb1, text = "one",  variable = rbCluster, value = 1L)
  tkconfigure(rb2, text = "two",  variable = rbCluster, value = 2L)
  tkconfigure(rb3, text = "three", variable = rbCluster, value = 3L)
  tkconfigure(rb4, text = "four", variable = rbCluster, value = 4L)
  onOK <- function() {
    clusterCount <<- as.integer(tclvalue(rbCluster))
    tkdestroy(win1)
  }
  butOK <- tk2button(win1, text = "OK", width = -8, command = onOK)

  # geometry manager
  tkgrid(tk2label(win1, text = "how many cores?"), padx = 10, pady = c(15, 5))
  tkgrid(rb1, padx = 10, pady = c(0, 5))
  tkgrid(rb2, padx = 10, pady = c(0, 15))
  tkgrid(rb3, padx = 10, pady = c(0, 15))
  tkgrid(rb4, padx = 10, pady = c(0, 15))
  tkgrid(butOK, padx = 10, pady = c(5, 15))
  tclAfter(5000, function() tkdestroy(win1)) # delay for prompt and then close window to proceed
  tkfocus(win1)
  tkwait.window(win1)
})

Après la fermeture de la fenêtre, clusterCount restera soit la valeur par défaut 1 ou peut être remplacé par 2, 3 ou 4.


0 commentaires