我想您要运行的程序存在缓冲问题。例如:
(defun program-stream (program &optional args)
(let ((process (sb-ext:run-program program args
:input :stream
:output :stream
:wait nil
:search t)))
(when process
(make-two-way-stream (sb-ext:process-output process)
(sb-ext:process-input process)))))
现在,在我的系统上,这将适用于cat
:
CL-USER> (defparameter *stream* (program-stream "cat"))
*STREAM*
CL-USER> (format *stream* "foo bar baz~%")
NIL
CL-USER> (finish-output *stream*) ; will hang without this
NIL
CL-USER> (read-line *stream*)
"foo bar baz"
NIL
CL-USER> (close *stream*)
T
注意finish-output http://clhs.lisp.se/Body/f_finish.htm– 如果没有这个,读取将会挂起。 (还有force-output http://clhs.lisp.se/Body/f_finish.htm.)
交互模式下的 Python 也可以工作:
CL-USER> (defparameter *stream* (program-stream "python" '("-i")))
*STREAM*
CL-USER> (loop while (read-char-no-hang *stream*)) ; skip startup message
NIL
CL-USER> (format *stream* "1+2~%")
NIL
CL-USER> (finish-output *stream*)
NIL
CL-USER> (read-line *stream*)
"3"
NIL
CL-USER> (close *stream*)
T
但如果你在没有-i
选项(或类似的选项,例如-u
),你可能会运气不好,因为缓冲正在进行。例如,在我的系统上,读取tr
将挂起:
CL-USER> (defparameter *stream* (program-stream "tr" '("a-z" "A-Z")))
*STREAM*
CL-USER> (format *stream* "foo bar baz~%")
NIL
CL-USER> (finish-output *stream*)
NIL
CL-USER> (read-line *stream*) ; hangs
; Evaluation aborted on NIL.
CL-USER> (read-char-no-hang *stream*)
NIL
CL-USER> (close *stream*)
T
Since tr
不提供关闭缓冲的开关,我们将使用 pty 包装器来包装调用(在本例中unbuffer
从预期):
CL-USER> (defparameter *stream* (program-stream "unbuffer"
'("-p" "tr" "a-z" "A-Z")))
*STREAM*
CL-USER> (format *stream* "foo bar baz~%")
NIL
CL-USER> (finish-output *stream*)
NIL
CL-USER> (read-line *stream*)
"FOO BAR BAZ
"
NIL
CL-USER> (close *stream*)
T
所以,长话短说:尝试使用finish-output
在阅读之前在流上。如果这不起作用,请检查阻止缓冲的命令行选项。如果仍然不起作用,您可以尝试将程序包装在某种 pty 包装器中。