2016-04-29 14 views
16

Diese Frage wurde von Rmarkdown not outputting results of system command to html file motiviert. Aus irgendeinem Grund kann die Ausgabe von system() in R (oder system2()) nicht von sink() oder capture.output() erfasst werden, daher gibt es derzeit keine Möglichkeit für knitr, die Ausgabe aufzuzeichnen. Zum Beispiel in der R-Konsole:So erfassen Sie die Ausgabe des Systems()

> system('ls') 
DESCRIPTION 
NAMESPACE 
R 
README.md 
inst 
man 

aber in einem knitr Dokument, werden Sie den Ausgang nicht sehen, weil capture.output(system('ls'))character(0) ist, das heißt die Ausgabe nicht erfasst werden können. Natürlich kann ich cat(system('ls', intern = TRUE), sep = '\n') tun, wie ich in der Antwort dieser Frage erwähnt habe, aber das ist irgendwie peinlich. Ich frage mich, ob es eine Möglichkeit ist, die Ausgabe von system() ohne Verwendung von intern = TRUE und cat() zu erfassen.


aktualisieren: siehe https://github.com/yihui/knitr/issues/1203 für einen Hack, die ich zur Verfügung gestellt, das Problem zu lösen.

Antwort

4

Sie könnten eine Funktion knitr::system, die Masken base::system hinzufügen. Benutzer können damit arbeiten, wie es system::base war, aber der Ausgang kann durch capture.output erfasst werden:

system <- function(...) { 
    stopifnot(!any(names(list(...)) %in% "intern")) 
    result <- base::system(..., intern = TRUE) 
    print(result) 
} 

Ich gebe zu, dass dies etwas hacky ist, und um ehrlich zu sein, ich bin über mögliche Nebenwirkungen nicht sicher. Aber ich denke, es könnte einen Versuch wert sein.

+0

Danke! Ich war mir dessen bewusst, aber ich würde es nicht verwenden, wenn ich einen Weg finde, die Ausgabe von 'system()' zu erfassen. Siehe meinen Kommentar unter Joshua Ulrichs Antwort. –

+0

@Yihui ist es nicht * das * schlecht - vor allem wenn man weiß, dass zB die Optionen 'ignore.stdout' und' ignore.stderr' in 'system' einfach'>/dev/null' oder '2>/dev/null' hinzufügen Umleitung (en) zum 'Befehl' :) – daroczig

5

Ich glaube nicht, dass Sie dies tun können (zumindest auf * nix systems; Ich habe kein Windows/Mac-System handlich), weil system scheinbar unsichtbar den Wert zurückgibt, der von dem ausgeführten Befehl zurückgegeben wird, und R doesn scheint die Ausgabe des Befehls nicht an die R-Konsole umzuleiten.

Dies ist, weil die stdout Ihres Terminals nicht das gleiche wie die R-Konsole "stdout" ist. Was Sie in Ihrer R-Sitzung sehen, ist der Mix aus stdout des Terminals und dem R-Prozess-Ausgang. capture.output sucht nach dem Ausgang des R-Prozesses, nicht alle Ausgabe an stdout aus dem übergeordneten Prozess.

Sie können einen Prozess starten, der auf stdout druckt, es in den Hintergrund stellen, dann R starten ... und Sie werden sehen, dass der Prozess in Ihrer "R-Ausgabe" ausgegeben wird, ähnlich wie wenn Sie system("ping -c5 8.8.8.8") ausgeführt hätten R.

[email protected]: /home/josh 
> ping -c5 8.8.8.8 & R 
[1] 5808 
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 
64 bytes from 8.8.8.8: icmp_seq=1 ttl=46 time=39.9 ms 

R version 3.2.4 Revised (2016-03-16 r70336) -- "Very Secure Dishes" 
Copyright (C) 2016 The R Foundation for Statistical Computing 
Platform: x86_64-pc-linux-gnu (64-bit) 

R is free software and comes with ABSOLUTELY NO WARRANTY. 
You are welcome to redistribute it under certain conditions. 
Type 'license()' or 'licence()' for distribution details. 

    Natural language support but running in an English locale 

R is a collaborative project with many contributors. 
Type 'contributors()' for more information and 
'citation()' on how to cite R or R packages in publications. 

Type 'demo()' for some demos, 'help()' for on-line help, or 
'help.start()' for an HTML browser interface to help. 
Type 'q()' to quit R. 

> 64 bytes from 8.8.8.8: icmp_seq=2 ttl=46 time=38.1 ms 
64 bytes from 8.8.8.8: icmp_seq=3 ttl=46 time=38.3 ms 
64 bytes from 8.8.8.8: icmp_seq=4 ttl=46 time=38.4 ms 
64 bytes from 8.8.8.8: icmp_seq=5 ttl=46 time=38.3 ms 

--- 8.8.8.8 ping statistics --- 
5 packets transmitted, 5 received, 0% packet loss, time 4003ms 
rtt min/avg/max/mdev = 38.176/38.656/39.986/0.703 ms 

> q() 
Save workspace image? [y/n/c]: n 
[1]+ Done     ping -c5 8.8.8.8 

[email protected]: /home/josh 
> 
+1

Ich glaube nicht, dass der unsichtbare zurückgegebene Wert das Problem ist. Ich erwarte 'capture.output()', um stdout zu erfassen, obwohl das nicht dokumentiert ist (die Dokumentation verwendete ein vages Wort "output" und ich weiß nicht, ob es stdout impliziert). Zum Beispiel können Sie 'capture.output ((function() {print (" Hallo Welt! "); Invisible (" hi ")})())' und es fängt 'Hallo Welt!' Von 'print()' . Meine eigentliche Frage ist, warum die Ausgabe von 'print()' erfasst werden kann, aber die Ausgabe von 'system()' nicht. Es ist entweder 'system()' nicht in stdout schreiben, oder 'capture.output()' erfasst nicht wirklich stdout. –

+0

@Yihui nicht, dass ich ein Experte für R internals bin, aber [diese] (https://github.com/wch/r-source/blob/e5b21d0397c607883ff25cca379687b86933d730/src/unix/sys-unix.c#L337) Linie _does_ suggeriert, 'system' verwendet' stdout' (entgegen meiner Erwartungen) – MichaelChirico

+0

@MichaelChirico Danke, dass Sie sich in den C-Code vertiefen. Dann denke ich, meine nächste Frage ist, welche Art von Ausgabe 'capture.output()' wirklich erfasst. –