如何异步读取子流程输出 [英] How to read subprocess output asynchronously
问题描述
我想实现一个futures::Stream
来读取和解析子子进程的标准输出.
I want to implement a futures::Stream
for reading and parsing the standard output of a child subprocess.
我现在在做什么:
-
生成子进程并通过
std::process
方法获取其stdout:let child = Command::new(...).stdout(Stdio.pipe()).spawn().expect(...)
spawn subprocess and obtain its stdout via
std::process
methods:let child = Command::new(...).stdout(Stdio.pipe()).spawn().expect(...)
将AsyncRead
和BufRead
添加到标准输出:
let stdout = BufReader::new(tokio_io::io::AllowStdIo::new(
child.stdout.expect("Failed to open stdout"),
));
为stdout声明包装器结构:
declare a wrapper struct for stdout:
struct MyStream<Io: AsyncRead + BufRead> {
io: Io,
}
实现Stream
:
impl<Io: AsyncRead + BufRead> Stream for MyStream<Io> {
type Item = Message;
type Error = Error;
fn poll(&mut self) -> Poll<Option<Message>, Error> {
let mut line = String::new();
let n = try_nb!(self.io.read_line(&mut line));
if n == 0 {
return Ok(None.into());
}
//...read & parse further
}
}
问题在于AllowStdIo
不会使ChildStdout
神奇地异步,并且self.io.read_line
调用仍会阻塞.
The problem is that AllowStdIo
doesn't make ChildStdout
magically asynchronous and the self.io.read_line
call still blocks.
我想我需要传递一些不同的东西而不是Stdio::pipe()
来使其异步,但是那又是什么呢?还是有其他解决方案?
I guess I need to pass something different instead of Stdio::pipe()
to have it asynchronous, but what? Or is there a different solution for that?
此问题不同于在future-rs中封装阻塞I/O的最佳方法是什么?,因为我想针对子进程的特定情况获取异步I/O,而不是解决同步I/O的封装问题.
This question is different from What is the best approach to encapsulate blocking I/O in future-rs? because I want to get asynchronous I/O for the specific case of a subprocess and not solve the problem of encapsulation of synchronous I/O.
更新:我正在使用tokio = "0.1.3"
来利用其运行时功能,并且当前不选择使用tokio-process
(
Update: I'm using tokio = "0.1.3"
to leverage its runtime feature and using tokio-process
is not an option at the moment (https://github.com/alexcrichton/tokio-process/issues/27)
推荐答案
tokio-process
板条箱为您提供了CommandExt
特征,可让您异步生成命令.
The tokio-process
crate provides you with a CommandExt
trait that allows you to spawn a command asynchronously.
生成的Child
具有用于ChildStdout
的吸气剂,该吸气剂实现了Read
并且是非阻塞的.
The resulting Child
has a getter for ChildStdout
which implements Read
and is non-blocking.
像您在示例中一样,将tokio_process::ChildStdout
包装到AllowStdIo
中应该可以使它工作!
Wrapping tokio_process::ChildStdout
into AllowStdIo
as you did in your example should make it work!
这篇关于如何异步读取子流程输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!