Warum ist message () eine bessere Wahl als print () in R, um ein Paket zu schreiben?


79

Ich hoffe zu wissen, warum dies message()eine bessere Wahl ist als print()beim Drucken von Diagnosemeldungen.

Zum Beispiel ist die print()Funktion eine bessere Wahl, um ein R-Objekt zu drucken, wie z. B. 'iris', message()wenn sie Zeichenfolgen verketten möchte, z . B. message("a", "b")kürzer als print(paste0("a", "b")).

Ich denke jedoch, dass es mehr Unterschiede gibt als die oben aufgeführten einfachen. Ich habe die Dokumentation für beide Methoden gelesen

aber es scheint, dass sie nicht so informativ sind, wie ich auf meine Frage gehofft hatte.

Ich würde mich freuen, wenn uns jemand mitteilen würde, in welchem ​​Fall message()besser ist als print()und warum.


1
@MartinMorgan, ich stimme dem größtenteils zu, message()signalisiere aber auch eine "Nachricht", die suppressMessages()erfasst wird. suppressMessages()Unterdrücken Sie keine reine stderr-Ausgabe, z. B. suppressMessages(cat("hello\n", file=stderr()))zeigt sie immer noch helloin der Konsole an.
HenrikB

@HenrikB stop, warning, messagealle Signalbedingungen, das ist , was sie fangen / Unterdrückungs-fähig macht tryCatch(message("hello"), message=force); cat(file=stderr())ist schlecht (und ineffektiv, wie Ihr Beispiel zeigt!), wenn die Absicht besteht, einen diagnostischen Zustand zu signalisieren.
Martin Morgan

Antworten:


138

TL; DR

Sie sollten verwenden, cat()wenn Sie die print.*()Funktionen für S3-Objekte erstellen. Für alles andere sollten Sie verwenden, es message()sei denn, der Status des Programms ist problematisch. zB schlechte Fehler, der erzielbare ist gibt warning()vs. Show stoppen Fehler Anwendungen stop().

Tor

Das Ziel dieses Beitrags ist es, Feedback zu den verschiedenen Ausgabeoptionen zu geben, auf die ein Paketentwickler Zugriff hat, und wie die Ausgabe strukturiert werden sollte, die möglicherweise auf einem neuen Objekt oder auf Zeichenfolgen basiert.

R Ausgabeübersicht

Die traditionellen Ausgabefunktionen sind:

  1. print()
  2. cat()
  3. message()
  4. warning()
  5. stop()

Jetzt senden die ersten beiden Funktionen ( print()und cat()) ihre Ausgabe an stdoutoder Standardausgabe. Die letzten drei Funktionen ( message(), warning(), und stop()) senden ihre Ausgabe an stderroder den Standardfehler. Das heißt, die Ergebnisausgabe eines Befehls wie lm()wird an eine Datei gesendet, und die Fehlerausgabe - falls vorhanden - wird an eine vollständig separate Datei gesendet. Dies ist besonders wichtig für die Benutzererfahrung, da die Ausgabe der Ergebnisse in Protokolldateien durch die Diagnose nicht überladen wird und Fehler zur schnellen Suche verfügbar sind.

Entwerfen für Benutzer und externe Pakete

Das Obige ist nun eher in einer E / A- Denkweise und nicht unbedingt in einem benutzerbezogenen Frameset dargestellt. Lassen Sie uns also im Kontext eines alltäglichen R-Benutzers eine gewisse Motivation dafür liefern. Insbesondere durch die Verwendung von 3-5 oder der stderrFunktionen kann deren Ausgabe unterdrückt werden, ohne über sink()oder mit dem Konsolentext zu basteln capture.output(). Die Unterdrückung kommt normalerweise in Form von suppressWarnings(), suppressMessages(), suppressPackageStartupMessages()und so weiter. Daher werden Benutzer nur mit ergebnisorientierten Ausgaben konfrontiert. Dies ist besonders wichtig, wenn Sie Benutzern die Flexibilität geben möchten, die textbasierte Ausgabe zu deaktivieren , wenn Sie dynamische Dokumente über Knitr , Rmarkdown oder Sweave erstellen .

Insbesondere knitrbietet chunk Optionen wie error = F, message = F, und warning = F. Dies ermöglicht die Reduzierung von Text, der einem Befehl im Dokument beigefügt ist. Darüber hinaus wird verhindert, dass die results = "hide"Option verwendet werden muss, mit der alle Ausgaben deaktiviert werden.

Besonderheiten der Ausgabe

drucken()

Als erstes haben wir einen Oldie, aber einen Goodie print(). Diese Funktion weist einige schwerwiegende Einschränkungen auf. Eine davon ist das Fehlen einer eingebetteten Verkettung von Begriffen. Das zweite und wahrscheinlich schwerwiegendere Problem ist die Tatsache, dass vor jeder Ausgabe [x]Zitate über den tatsächlichen Inhalt stehen. Das xbezieht sich in diesem Fall auf die zu druckende Elementnummer. Dies ist hilfreich für Debugging-Zwecke, hat aber darüber hinaus keinen Zweck.

z.B

print("Hello!")

[1] "Hello!"

Für die Verkettung verlassen wir uns auf die paste()Funktion, die synchron arbeitet mit print():

print(paste("Hello","World!"))

[1] "Hello World!"

Alternativ kann man die paste0(...)Funktion anstelle von verwenden paste(...), um die Standardverwendung von a spacezwischen Elementen zu vermeiden, die durch paste()den sep = " "Parameter von ' gesteuert werden. (auch bekannt als Verkettung ohne Leerzeichen)

z.B

print(paste0("Hello","World!"))

[1] "HelloWorld!"

print(paste("Hello","World!", sep = ""))

[1] "HelloWorld!"

Katze()

Auf der anderen Seite werden cat()all diese Kritikpunkte angesprochen. Vor allem des sep=" "Parameter der paste()ist Funktionalität gebaut eine in denen ein Schreiben überspringen paste()innerhalb cat(). Der cat()einzige Nachteil der Funktion ist jedoch, dass Sie neue Zeilen über das \nAnhängen am Ende oder fill = TRUE(verwendet die Standarddruckbreite) erzwingen müssen .

z.B

cat("Hello!\n")
Hello!

cat("Hello","World!\n")
Hello World!

cat("Hello","World!\n", sep = "")
HelloWorld!

Genau aus diesem Grund sollten Sie cat()beim Entwerfen einer print.*()S3-Methode verwenden.

Botschaft()

Die message()Funktion ist einen Schritt besser als gerade cat()! Der Grund dafür ist, dass sich die Ausgabe von herkömmlichem Klartext unterscheidet, da sie stderrstattdessen an gerichtet ist stdout. ZB Sie haben die Farbe von der Standardausgabe Schwarz auf Rot geändert, um die Aufmerksamkeit des Benutzers auf sich zu ziehen.

Nachrichtenausgabe

Darüber hinaus verfügen Sie über die integrierte paste0()Funktionalität.

message("Hello ","World!") # Note the space after Hello
"Hello World!"

Darüber hinaus message()bietet ein Fehlerzustand, mit dem verwendet werden kanntryCatch()

z.B

 tryCatch(message("hello\n"), message=function(e){cat("goodbye\n")})
 goodbye

Warnung()

Die warning()Funktion ist nicht zufällig zu verwenden. Die Warnfunktion unterscheidet sich von der Nachrichtenfunktion hauptsächlich dadurch, dass ihr eine Zeile vorangestellt wird ( "Warning message:") und ihr Status als problematisch angesehen wird.

Warnausgang

Sonstiges: Die gelegentliche Verwendung in einer Funktion kann beim Versuch, das Paket auf CRAN hochzuladen, versehentlich Herzschmerz auslösen, da Beispielprüfungen und Warnungen normalerweise als "Fehler" behandelt werden.

halt()

Zu guter Letzt haben wir stop(). Dies bringt Warnungen auf die nächste Ebene, indem die vorliegende Aufgabe vollständig beendet und die Kontrolle an den Benutzer zurückgegeben wird. Darüber hinaus hat es das schwerwiegendste Präfix mit dem "Error:"hinzugefügten Begriff .

Fehlerausgabe


Was ist der Unterschied zwischen message("hello world")und cat("hello world", sep="\n")beim Entwerfen eines Drucks. * S3-Methode?
Antonio

1
@antonio: message()wird roten Text haben und der andere wird nicht. Wenn Sie nun beispielsweise eine Variable hinzufügen cat, beträgt cat("hello world", "antonio", sep="\n")der Unterschied eine Zeile mit hello worldund eine andere mit antonio. Trotzdem message()wird alles auf der gleichen Linie bleiben.
Mantel

1
Danke für die tolle Antwort. Ich suchte nach etwas Ähnlichem, aber meine Frage wurde als "faul" bezeichnet: stackoverflow.com/questions/36065232/…
Burger


1
@WaldirLeoncio "Diagnostic" -Ausgabe wird beispielsweise zum Beispiel "at level info" gedruckt. Leider existiert dieses Konzept mit message()oder nicht cat(). Ich habe mir angesehen, ob es eine ausgereifte Protokollierungsschnittstelle für R gibt, wie es heute bei den meisten Systemen der Fall ist (z. B. die slf4j- API für Java), und es gibt : futile.logger - Bei CRAN .
David Tonhofer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.