Common lisp 如何正确读取大型进程输出

Common lisp 如何正确读取大型进程输出,common-lisp,sbcl,Common Lisp,Sbcl,关于如何从流程流中读取数据,已经有了很多讨论,但据我所知,这些讨论不包括从以下流程中读取数据: 在进行任何输出之前,可能会运行很长时间 在其生命周期结束时产生巨大的输出(超过流缓冲区所能容纳的容量) 不应超过给定的时间范围 结果输出作为一个整体需要(长字符串) 因此,使用上述解决方案会导致浪费进程周期,因为即使没有输出,循环也会尝试读取流,或者解决方案不会终止,因为进程无法打印其整个输出(由于缓冲区已满),并且输出处理程序在读取前等待进程终止 我当前的解决方案是这样的(灵感来源于大容量读取大

关于如何从流程流中读取数据,已经有了很多讨论,但据我所知,这些讨论不包括从以下流程中读取数据:

  • 在进行任何输出之前,可能会运行很长时间
  • 在其生命周期结束时产生巨大的输出(超过流缓冲区所能容纳的容量)
  • 不应超过给定的时间范围
  • 结果输出作为一个整体需要(长字符串)
因此,使用上述解决方案会导致浪费进程周期,因为即使没有输出,循环也会尝试读取流,或者解决方案不会终止,因为进程无法打印其整个输出(由于缓冲区已满),并且输出处理程序在读取前等待进程终止

我当前的解决方案是这样的(灵感来源于大容量读取大文件的解决方案)

通过一个进程调用该函数:

(sb-ext:run-program "/path/to/programm"
                           (list "--params" "foo" "bar") 
                           :output :stream :wait nil)
但这种解决方案有其缺点:

  • 它不工作,因为流未与文件关联(错误)
  • 它的一般睡眠时间为1,即使当时可能没有输出
  • 它进行了大量的连接,这似乎是一个不雅观的解决方案
已退出/停止/运行时间过长的进程的最终处理/清理由调用函数处理

如何从以下流程中读取:

  • 可能会运行很长时间(并在其生命周期结束时进行输出)
  • 可能使输出大于流缓冲区
  • 运行时间不得超过给定的时间跨度
  • 整体上需要输出

字符串输出流是否适合您?输出将存储在您随后返回的字符串中,因此缓冲不应该是一个太大的问题。例如:

* (with-output-to-string (out)
    (sb-ext:run-program "/bin/ls" '("/") :output out))

"bin
boot
…
vmlinuz
vmlinuz.old
"
如果要预分配字符串,可以使用的string form参数对进行预分配


不过,您不必使用with output to string来使用字符串输出流。您还可以使用创建一个并将其传递给sb ext:run程序。你最终会从中获得文本。

是否首先将输出重定向到一个文件,然后再读取该文件是一个选项?由于此函数将被多次调用,我宁愿不要,因为这将导致硬盘上大量不必要的写入和读取。虽然如果在RAM中有一个文件可能是一个不错的选择如果你担心流缓冲区的大小,你可以使用一个字符串输出流(如果你知道它有多大的话,可能是一个预分配的字符串)。那么你就不必担心缓冲区的大小了。不是重复的,而是相关的,因为问题演示了在这里的答案中使用的技术。更接近于复制品,但仍不完全相同。
* (with-output-to-string (out)
    (sb-ext:run-program "/bin/ls" '("/") :output out))

"bin
boot
…
vmlinuz
vmlinuz.old
"