[英]Simultaneously save and print R system call output?
Within my R script I am calling a shell script.在我的 R 脚本中,我正在调用 shell 脚本。 I would like to both print the output to the console in real time and save the output for debugging.
我想将 output 实时打印到控制台并保存 output 以进行调试。 For example:
例如:
system("script.sh")
prints to console in real time,实时打印到控制台,
out <- system("script.sh", intern = TRUE)
saves the output to a variable for debugging, and将 output 保存到一个变量中进行调试,并且
(out <- system("script.sh", intern = TRUE))
will only print the contents of out
after the script has finished.只会在脚本完成后打印
out
的内容。 Is there any way to both print to console in real time and store the output as a variable?有什么方法可以实时打印到控制台并将 output 作为变量存储?
Since R is waiting for this to complete anyway, generally to see the stdout in real time , you need to poll the process for output.由于 R 无论如何都在等待这个完成,一般要实时看到标准输出,你需要轮询 output 的进程。 (One can/should also poll for stderr, depending.)
(一个可以/应该也轮询stderr,这取决于。)
Here's a quick example using processx
.这是一个使用
processx
的快速示例。
First, I'll create a slow-output shell script;首先,我将创建一个慢输出 shell 脚本; replace this with the real reason you're calling
system
.将其替换为您调用
system
的真正原因。 I've named this myscript.sh
.我已将此命名为
myscript.sh
。
#!/bin/bash
for i in `seq 1 5` ; do
sleep 3
echo 'hello world: '$i
done
Now let's (1) start a process in the background, then (2) poll its output every second.现在让我们(1)在后台启动一个进程,然后(2)每秒轮询它的 output。
proc <- processx::process$new("bash", c("-c", "./myscript.sh"), stdout = "|")
output <- character(0)
while (proc$is_alive()) {
Sys.sleep(1)
now <- Sys.time()
tmstmp <- sprintf("# [%s]", format(now, format = "%T"))
thisout <- proc$read_output_lines()
if (length(thisout)) {
output <- c(output, thisout)
message(tmstmp, " New output!\n", paste("#>", thisout))
} else message(tmstmp)
}
# [13:09:29]
# [13:09:30]
# [13:09:31]
# [13:09:32]New output!
#> hello world: 1
# [13:09:33]
# [13:09:34]
# [13:09:35]New output!
#> hello world: 2
# [13:09:36]
# [13:09:37]
# [13:09:38]New output!
#> hello world: 3
# [13:09:39]
# [13:09:40]
# [13:09:41]New output!
#> hello world: 4
# [13:09:42]
# [13:09:43]
# [13:09:44]New output!
#> hello world: 5
And its output is stored:其output存储:
output
# [1] "hello world: 1" "hello world: 2" "hello world: 3" "hello world: 4" "hello world: 5"
Ways that this can be extended:可以扩展的方法:
Add/store a timestamp with each message, so you know when it came in. The accuracy and utility of this depends on how frequently you want R to poll the process stdout pipe, and really how much you need this information.为每条消息添加/存储时间戳,这样您就知道它什么时候进来了。这取决于您希望 R 多久轮询进程标准输出 pipe,以及您需要多少此信息。
Run the process in the background, and even poll for it in the background cycles.在后台运行该进程,甚至在后台循环中轮询它。 I use the
later
package and set up a self-recurring function that polls, appends, and re-submits itself into the later
process queue.我使用
later
的 package 并设置了一个自循环的 function 来轮询、附加并重新提交到later
的进程队列中。 The benefit of this is that you can continue to use R;这样做的好处是可以继续使用R; the drawback is that if you're running long code, then you will not see output until your current code exits and lets R breathe and do something idly.
缺点是,如果您正在运行长代码,那么在您当前的代码退出并让 R 呼吸并无所事事之前,您将看不到 output。 (To understand this bullet, one really must play with the
later
package, a bit beyond this answer.) (要理解这个子弹,真的必须玩
later
的 package,有点超出这个答案。)
Depending on your intentions, it might be more appropriate for the output to go to a file and "permanently" store it there instead of relying on the R process to keep tabs.根据您的意图,将 output 到 go 到文件中并“永久”将其存储在那里而不是依靠 ZE1E1D3D40573127E9EE0480CAF1283D 过程可能更合适There are disadvantages to this, in that now you need to manage polling a file for changes, and R isn't making that easy (it does not have, for instance, direct/easy access to
inotify
, so now it gets even more complicated).这样做有缺点,因为现在您需要管理轮询文件以进行更改,而 R 并没有那么容易(例如,它没有直接/轻松访问
inotify
,所以现在它变得更加复杂)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.