这似乎与已提出的其他几个问题(例如这个)非常相关,但我无法完全弄清楚如何做我想要的。也许替换函数是错误的工作工具,这也是一个完全可以接受的答案。我对 Python 比对 R 更熟悉,我可以很容易地想到我想在 Python 中如何做,但我不太清楚如何在 R 中处理它。
问题:我试图在函数中修改一个对象,而不必返回它,但我不需要传入修改它的值,因为这个值是已经包含的函数调用的结果在对象中。
更具体地说,我有一个列表(从技术上讲,它是一个 s3 类,但我认为这实际上与这个问题无关),其中包含一些与以processx::process$new()
call 开头的进程相关的内容。为了重现性,这里有一个可以运行的玩具 shell 脚本,以及获取我的res
对象的代码:
echo '
echo $1
sleep 1s
echo "naw 1"
sleep 1s
echo "naw 2"
sleep 1s
echo "naw 3"
sleep 1s
echo "naw 4"
sleep 1s
echo "naw 5"
echo "All done."
' > naw.sh
然后我的包装是这样的:
run_sh <- function(.args, ...) {
p <- processx::process$new("sh", .args, ..., stdout = "|", stderr = "2>&1")
return(list(process = p, orig_args = .args, output = NULL))
}
res <- run_sh(c("naw.sh", "hello"))
应该res
看起来像
$process
PROCESS 'sh', running, pid 19882.
$output
NULL
$orig_args
[1] "naw.sh" "hello"
所以,这里的具体问题有点特殊,process$new
但我认为一般原则是相关的。我试图在完成后收集该进程的所有输出,但您只能调用process$new$read_all_output_lines()
(或它的兄弟函数)一次,因为它第一次将从缓冲区返回结果,而随后它什么也不返回。另外,我将调用其中的一堆,然后再回来“检查它们”,所以我不能立即调用res$process$read_all_output_lines()
,因为它会在函数返回之前等待进程完成,这不是我的想。
所以我试图存储该调用的输出,res$output
然后保留它并在后续调用中返回它。Soooo ...我需要一个功能res
res$output <- res$process$read_all_output_lines()
来修改。
这是我尝试过的,基于这样的指导,但没有奏效。
get_output <- function(.res) {
# check if process is still alive (as of now, can only get output from finished process)
if (.res$process$is_alive()) {
warning(paste0("Process ", .res$process$get_pid(), " is still running. You cannot read the output until it is finished."))
invisible()
} else {
# if output has not been read from buffer, read it
if (is.null(.res$output)) {
output <- .res$process$read_all_output_lines()
update_output(.res) <- output
}
# return output
return(.res$output)
}
}
`update_output<-` <- function(.res, ..., value) {
.res$output <- value
.res
}
get_output(res)
第一次调用有效,但它不会将输出存储res$output
到以后访问,因此后续调用什么也不返回。
我也尝试过这样的事情:
`get_output2<-` <- function(.res, value) {
# check if process is still alive (as of now, can only get output from finished process)
if (.res$process$is_alive()) {
warning(paste0("Process ", .res$process$get_pid(), " is still running. You cannot read the output until it is finished."))
.res
} else {
# if output has not been read from buffer, read it
if (is.null(.res$output)) {
output <- .res$process$read_all_output_lines()
update_output(.res) <- output
}
# return output
print(value)
.res
}
}
这只是扔掉了,value
但这感觉很愚蠢,因为你必须用get_output(res) <- "fake"
我讨厌的任务来调用它。
显然我也可以只返回修改后的res
对象,但我不喜欢这样,因为用户必须知道该怎么做res <- get_output(res)
,如果他们忘记这样做(第一次),那么输出就会丢失到以太并且永远不会恢复了。不好。
任何帮助深表感谢!