Связь с подпроцессом Python - PullRequest
       0

Связь с подпроцессом Python

0 голосов
/ 20 февраля 2020

У меня есть следующий код Rust, который отправляет строку в подпроцесс через stdin и читает все, что приходит от него stdout:

use std::io::{BufRead, BufReader, Write};
use std::process::{Command, Stdio};
fn main() {
   let mut child = Command::new("cat")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Did not run");
    let v = vec!["11111", "2222222", "3333", "end", "soooooooooooooooo"];
    let k = child.stdin.as_mut().unwrap();
    let mut g = BufReader::new(child.stdout.as_mut().unwrap());
    for x in v.into_iter() {
        k.write_all(x.as_bytes()).unwrap();
        k.write_all("\n".as_bytes()).unwrap();
        let mut s: String = String::new();
        g.read_line(&mut s).unwrap();
        println!("{}", s)
    }
}

Пример запускается без проблем, но когда я пытаюсь сделать то же самое с использованием сценария python не удается.

Чтобы вызвать сценарий, я создаю child следующим образом:

    let mut child = Command::new("c:\\Windows\\py.exe")
        .args(&["-u", "echo.py"])

И в сценарии я просто повторяю все приходит от stdin до stdout

import sys
import time
if __name__=="__main__":
    fo=sys.stdout
    fo.write('python starts at: %.0f\n'%(time.time()*1000))
    line = sys.stdin.readline()
    while True:
        fo.write(line+"\n")
        line = sys.stdin.readline()
    fo.write('python ends at: %.0f\n'%(time.time()*1000))

Вывод, который я получаю:

python starts at: 1582166542281                                                                

11111                                                                                          



2222222                                                                                        



Traceback (most recent call last):                                                             
  File "c:\Users\asia\Documents\projects\python\echo.py", line 8, in <module>                  
    fo.write(line+"\n")                                                                        
OSError: [Errno 22] Invalid argument                                                           

Мой пример - разрыв трубы при печати второй строки, но я могу не понимаю почему. Что мне здесь не хватает?

Заранее спасибо

1 Ответ

1 голос
/ 20 февраля 2020

Процесс Rust записывает 5 строк в стандартный поток процесса python, именно строки, получаемые из:

let v = vec!["11111", "2222222", "3333", "end", "soooooooooooooooo"];

Но на стороне python вы пытаетесь записать обратно в ржавчину 7 строк: заголовок, 5 строк из stdin и нижний колонтитул.

read_line внутри for x in v.into_iter() читает только 5 строк, и процесс ржавчины завершается, вызывая BrokenPipe на python стороне, которая должна напишите еще две строки.

Я думаю, что также необходим некоторый элемент управления для выхода while True l oop на python стороне.

Что-то в этом духе, просто чтобы получить идея:

use std::io::{BufRead, BufReader, Write};
use std::process::{Command, Stdio};
fn main() {
   let mut child = Command::new("python").args(&["-u", "echo.py"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Did not run");
    let v = vec!["11111", "2222222", "3333", "end", "soooooooooooooooo"];
    let k = child.stdin.as_mut().unwrap();
    let mut g = BufReader::new(child.stdout.as_mut().unwrap());

    // read the header "python starts at ..."
    let mut s: String = String::new();
    g.read_line(&mut s).unwrap();
    println!("{}", s);

    for x in v.into_iter() {
        k.write_all(x.as_bytes()).unwrap();
        k.write_all("\n".as_bytes()).unwrap();
        let mut s: String = String::new();

        // read len(v) lines, in this case 5 lines
        g.read_line(&mut s).unwrap();
        println!("{}", s)
    }

    // Something is neeeded to signal termination of input
    // assume for this example a zero length string
    k.write_all("\n".as_bytes()).unwrap();

    // read the empty string and the footer "python ends at ..."
    let mut s: String = String::new();
    g.read_line(&mut s).unwrap();
    g.read_line(&mut s).unwrap();
    println!("{}", s);
}

python:

import sys
import time

if __name__ == "__main__":
    fo = sys.stdout
    fo.write('python starts at: %.0f\n' % (time.time()*1000))
    line = sys.stdin.readline()
    while True:
        fo.write(line)
        line = sys.stdin.readline()
        if (line == "\n"):
            break

    fo.write('python ends at: %.0f\n' % (time.time()*1000))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...