Need help with external program comunication!

Hello! Can anybody explain me how can i call external executable program from rust, get it's output and send commands to stdin of that external program?

You should have a look at the process module of the standard library. You can create a child process running your external executable with Command and use Command::spawn to get a handle to that process's stdout and stdin (see the Child struct).

Thanks for answering! I've seen that module and i faced the folowing problem: I can send to child's prosess stdin only one command and after that process closes. I see its output but can't send another command.

It would probably help if you showed the code you have attempted to use.

I think most of us would probably want to provide you with an adequate answer instead of trying to interpret the issue based on how you have interpreted it.

use std::io::{Read, Write};
use std::process::{Command, Stdio};

fn main() {
    let mut child = Command::new(r#"C:\Python\Python39-32\python.exe"#)
        .arg(r#"D:\main.py"#)
        .current_dir(r#"D:\"#)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Failed to start process");

    child.stdin.unwrap().write_all("send command 1".as_bytes());
    let mut buffer = String::from("");
    child.stdout.unwrap().read_to_string(&mut buffer); //got answer from process stdout

    if buffer == "answer from python script" {
        //child.stdin.unwrap().write_all("send command 2".as_bytes());   <- can't use child.stdin for the second time.
        //child.stdout.unwrap().read_to_string(&mut buffer);             <- the same with child.stdout, can't read from it.
    }
}

(Playground)

That's because you move the stdin/stdout handle. Write .as_mut().unwrap() instead to only borrow it.

Unfurtunately it isn't working. When i changed to:
child.stdin.as_mut().unwrap().write_all("send command 1".as_bytes());
child.stdout.as_mut().unwrap().read_to_string(&mut buffer);
I didn't get any response from process and process got blocked (i think).
Actualy it gets "command 1" , performs it and then bloks.

It does make it compile, though.

As for the program's behavior, you'll have to check what you have to do to actually make it wait (or not wait) for the next line. You could try flushing the stdin after every line, or simply sending a newline character at the end.

1 Like

Thank you mate! This is a brakethrough! Sending commands to the process and receiving responses works perfectly!

    let mut buf = [0; 1024];
    child.stdin.as_mut().unwrap().write_all("command 1".as_bytes());
    child.stdin.as_mut().unwrap().write_all("\n".as_bytes());
    child.stdin.as_mut().unwrap().flush();
    child.stdout.as_mut().unwrap().read(&mut buf);
    println!("{}", std::str::from_utf8(&buf).unwrap());
    child.stdin.as_mut().unwrap().write_all("command 2".as_bytes());
    child.stdin.as_mut().unwrap().write_all("\n".as_bytes());
    child.stdin.as_mut().unwrap().flush();
    child.stdout.as_mut().unwrap().read(&mut buf);
    println!("{}", std::str::from_utf8(&buf).unwrap());

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.