如何异步读取子流程输出 [英] How to read subprocess output asynchronously

查看:149
本文介绍了如何异步读取子流程输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个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(...)

AsyncReadBufRead添加到标准输出:

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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆