简体   繁体   English

同时保存打印R系统调用output?

[英]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:可以扩展的方法:

  1. 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,以及您需要多少此信息。

  2. 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,有点超出这个答案。)

  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM