我想实现一个futures::Stream
来读取和解析子子进程的标准输出。
我现在在做什么:
生成子流程并通过std::process
方法获取其标准输出:let child = Command::new(...).stdout(Stdio.pipe()).spawn().expect(...)
将AsyncRead
和BufRead
添加到stdout:
let stdout = BufReader::new(tokio_io::io::AllowStdIo::new(
child.stdout.expect("Failed to open stdout"),
));
为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
调用仍会阻止。
我想我需要传递一些不同的东西而不是Stdio::pipe()
才能让它异步,但是什么呢?或者是否有不同的解决方案?
这个问题与What is the best approach to encapsulate blocking I/O in future-rs?不同,因为我希望针对子进程的特定情况获得异步I / O,而不是解决同步I / O的封装问题。
更新:我正在使用tokio = "0.1.3"
来利用其运行时功能,目前使用tokio-process
不是一个选项(https://github.com/alexcrichton/tokio-process/issues/27)
答案 0 :(得分:2)
tokio-process
crate为您提供CommandExt
特征,允许您异步生成命令。
生成的Child
有ChildStdout
的getter,它实现Read
并且是非阻塞的。
如您在示例中所做的那样将tokio_process::ChildStdout
包装到AllowStdIo
中应该可以使其正常工作!