R Les numéros de ligne de script à l'erreur?

si j'exécute un long script R depuis la ligne de Commande (R --slave script.R), Comment puis-je obtenir pour donner des numéros de ligne à des erreurs?

Je ne veux pas ajouter de commandes de débogage au script si possible -- je veux juste que R se comporte comme la plupart des autres langues de script ...

86
demandé sur forkandwait 2009-09-18 21:47:29

5 réponses

cela ne vous donnera pas le numéro de ligne, mais vous indiquera où l'échec se produit dans la pile d'appels ce qui est très utile:

traceback()

[Edit:] lors de l'exécution d'un script à partir de la ligne de commande, vous devrez sauter un ou deux appels, voir traceback () pour des sessions R interactives et non interactives

Je ne suis pas au courant d'une autre façon de faire cela sans les suspects habituels de débogage:

  1. debug ()
  2. de votre navigateur (en)
  3. options(erreur=récupérer) [suivi par des options(erreur = NULL) pour annuler]

Vous pouvez jeter un oeil à ce poste.

[Edit:] Sorry...juste vu que vous exécutez cette ligne de commande. Dans ce cas, je suggérerais de travailler avec les options(erreur) fonctionnalité. Voici un exemple simple:

options(error = quote({dump.frames(to.file=TRUE); q()}))

vous pouvez créer un script aussi élaboré que vous le voulez à une condition d'erreur, donc vous devez juste décider quelles informations vous avez besoin pour déboguer.

sinon, s'il y a des zones spécifiques qui vous préoccupent (par exemple se connecter à une base de données), alors enveloppez-les dans une fonction tryCatch ().

34
répondu Shane 2017-05-23 11:47:09

Faire options(error=traceback) fournit un peu plus d'informations sur le contenu des lignes menant à l'erreur. Il fait apparaître un traceback s'il y a une erreur, et pour certaines erreurs il a le numéro de ligne, préfixé par # . Mais c'est hit ou miss, beaucoup d'erreurs n'obtiendront pas de numéros de ligne.

10
répondu Hugh Perkins 2017-03-28 23:11:52

le soutien pour ceci sera disponible dans R 2.10 et plus tard. Duncan Murdoch vient d'être affecté à r-devel le 10 septembre 2009 à propos de findLineNum et setBreapoint :

I've just added a couple of functions to R-devel to help with
debugging.  findLineNum() finds which line of which function corresponds
to a particular line of source code; setBreakpoint() takes the output of
findLineNum, and calls trace() to set a breakpoint there.

These rely on having source reference debug information in the code.
This is the default for code read by source(), but not for packages.  To
get the source references in package code, set the environment variable
R_KEEP_PKG_SOURCE=yes, or within R, set options(keep.source.pkgs=TRUE),
then install the package from source code.  Read ?findLineNum for
details on how to
tell it to search within packages, rather than limiting the search to
the global environment.

For example,

x <- " f <- function(a, b) {
             if (a > b)  {
                 a
             } else {
                 b
             }
         }"


eval(parse(text=x))  # Normally you'd use source() to read a file...

findLineNum("<text>#3")   # <text> is a dummy filename used by parse(text=)

This will print

 f step 2,3,2 in <environment: R_GlobalEnv>

and you can use

setBreakpoint("<text>#3")

to set a breakpoint there.

There are still some limitations (and probably bugs) in the code; I'll
be fixing thos
9
répondu Dirk Eddelbuettel 2017-03-28 06:44:09

spécifiant l'option globale R pour traiter les erreurs non catastrophiques a fonctionné pour moi, avec un flux de travail personnalisé pour conserver les informations sur l'erreur et l'examen de ces informations après la défaillance. J'exécute actuellement la version 3.4.1 de R Ci-dessous, j'ai inclus une description du workflow qui a fonctionné pour moi, ainsi que du code que j'ai utilisé pour définir L'option globale de gestion des erreurs dans R.

comme je l'ai configuré, le traitement des erreurs crée aussi un fichier RData contenant tous les objets dans la mémoire de travail au moment de l'erreur. Ce dump peut être lu dans R en utilisant load() et puis les différents environnements tels qu'ils existaient au moment de l'erreur peuvent être inspectés de façon interactive en utilisant debugger(errorDump) .

je vais noter que j'ai pu obtenir des numéros de ligne dans la sortie traceback() à partir de n'importe quelle fonction personnalisée dans la pile, mais seulement si j'ai utilisé l'option keep.source=TRUE en appelant source() pour n'importe quelle fonction personnalisée utilisée dans mon script. Sans cette option, la définition de l'option globale de gestion des erreurs comme ci-dessous envoyait la pleine sortie du traceback() à un journal des erreurs nommé error.log , mais les numéros de ligne n'étaient pas disponibles.

Voici les étapes générales que j'ai prises dans mon workflow et comment j'ai pu accéder à la mémoire et au journal des erreurs après une panne R non interactive.

  1. la ligne de commande. Cette option permet de définir l'option globale de gestion des erreurs pour la session R. Mon script principal s'appelait myMainScript.R . Les différentes lignes du code ont des commentaires après elles décrivant ce qu'elles font. Fondamentalement, avec cette option , lorsque R rencontre une erreur qui déclenche stop() , il va créer un RData (*.rda) dump fichier de la mémoire de travail à travers tous les environnements actifs dans le répertoire ~/myUsername/directoryForDump et va également écrire un journal des erreurs nommé error.log avec quelques informations utiles à la même répertoire. Vous pouvez modifier ce fragment pour ajouter d'autres manipulations en cas d'erreur (par exemple, ajouter un timestamp au fichier dump et les noms de fichiers du journal des erreurs, etc.).

    options(error = quote({
      setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
      dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
      sink(file="error.log"); # Specify sink file to redirect all output.
      dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
      cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
      cat('\nTraceback:');
      cat('\n');
      traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
      sink();
      q()}))
    
  2. assurez-vous que du script principal et de tous les appels de fonction ultérieurs, à chaque fois qu'une fonction est fournie, l'option keep.source=TRUE est utilisée. C'est-à-dire, pour obtenir une fonction, vous utiliseriez source('~/path/to/myFunction.R', keep.source=TRUE) . Ceci est requis pour que la sortie traceback() contienne des numéros de ligne. Il semble comme vous pouvez également être en mesure de définir cette option globalement en utilisant options( keep.source=TRUE ) , mais je ne l'ai pas testé pour voir si cela fonctionne. Si vous n'avez pas besoin des numéros de ligne, vous pouvez omettre cette option.

  3. depuis le terminal (en dehors de R), appeler le script principal en mode batch en utilisant Rscript myMainScript.R . Cela démarre une nouvelle session R non interactive et exécute le script myMainScript.R . L'extrait de code donné à l'étape 1 qui a été placé en haut de myMainScript.R définit la manipulation d'erreur l'option pour la non-interactif de recherche de la session.
  4. Rencontre une erreur quelque part dans l'exécution de myMainScript.R . Cela peut être dans le script principal lui-même, ou imbriqué plusieurs fonctions profondes. Lorsque l'erreur est rencontrée, le traitement sera effectué comme spécifié à l'étape 1, et la session R se terminera.
  5. un fichier dump RData nommé errorDump.rda et et le journal des erreurs nommé error.log sont créés dans le répertoire spécifié par '~/myUsername/directoryForDump' dans le configuration globale des options de traitement des erreurs.
  6. à votre guise, inspectez error.log pour examiner les renseignements sur l'erreur, y compris le message d'erreur lui-même et la trace complète de la pile menant à l'erreur. Voici un exemple du journal généré par erreur; notez que les numéros qui suivent le caractère # sont les numéros de ligne de l'erreur à divers points de la pile d'appels:

    Error in callNonExistFunc() : could not find function "callNonExistFunc"
    Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
    
    Traceback:
    3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
    2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
    1: test_multi_commodity_flow_cmd(config_file_path = config_file_path, 
    spot_file_path = spot_file_path, forward_file_path = forward_file_path, 
    data_dir = "../", user_dir = "Output", sim_type = "spot", 
    sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw", 
    nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31", 
    compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes, 
    overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime, 
    ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
    
  7. à votre loisirs, vous pouvez charger errorDump.rda dans une session R interactive en utilisant load('~/path/to/errorDump.rda') . Une fois chargé, appelez debugger(errorDump) pour parcourir tous les objets R en mémoire dans n'importe lequel des environnements actifs. Pour plus d'informations, consultez la rubrique R aide sur debugger() .

ce flux de travail est extrêmement utile lors de l'exécution de R dans un certain type d'environnement de production où vous avez des sessions r non-interactives étant lancées à la ligne de commande et vous voulez que l'information conservée sur les erreurs inattendues. La possibilité de décharger de la mémoire dans un fichier que vous pouvez utiliser pour inspecter la mémoire de travail au moment de l'erreur, ainsi que d'avoir les numéros de ligne de l'erreur dans la pile d'appel, faciliter le débogage post-mortem rapide de ce qui a causé l'erreur.

2
répondu bmosov01 2017-09-10 05:01:29

vous le faites en paramétrant

options(show.error.locations = TRUE)

je me demande juste pourquoi ce paramètre n'est pas un défaut dans R? Il faut, comme dans toute autre langue.

0
répondu TMS 2016-10-11 09:52:30