简体   繁体   中英

Pipe to python process from c# unity

I have a unity (C#) app that is calling a python script by initialising a child process.

When trying to write to the python std::in, I seem to be getting a

write fault on path

error when writing to STD::IN.

When reading from the process's STD::OUT, I get null as a value output.

What's the best way to pipe to the python process for input/output?

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using System.Diagnostics;

public class PythonCaller : MonoBehaviour
{
private string buffer = "";
private Process pythonML;

// Use this for initialization
void Start () {
    this.pythonML = new System.Diagnostics.Process();
    this.pythonML.StartInfo.FileName = "/bin/bash";
    this.pythonML.StartInfo.Arguments =
        "{{path to python executable}}/python {{path to python script}}/test.py";
    this.pythonML.StartInfo.UseShellExecute = false;
    this.pythonML.StartInfo.RedirectStandardInput = true;
    this.pythonML.StartInfo.RedirectStandardOutput = true;
    this.pythonML.StartInfo.RedirectStandardError = true;
    this.pythonML.Start();
    this.pythonML.BeginOutputReadLine();
    this.pythonML.OutputDataReceived += new DataReceivedEventHandler((sender, e) => {
        UnityEngine.Debug.Log(e.Data);
    });
    this.pythonML.WaitForExit();
}

// Update is called once per frame
void Update () {
    foreach (char c in Input.inputString) {
        if (c == '\b') {
            if (this.buffer.Length > 0) {
                this.buffer = this.buffer.Substring(0, this.buffer.Length - 1);
            }
        } else if (c == '\n' || c == '\r') {
            try {
                UnityEngine.Debug.Log(this.buffer);
                this.pythonML.StandardInput.WriteLine(this.buffer);

            }
            catch (IOException e) {
                UnityEngine.Debug.Log(e.Message);
            }

            this.buffer = "";
        } else {
            this.buffer += c;
        }
    }
}

}

PYTHON CODE:

print('hello world!')

I think you need to redirect standard input for this to work. You already have that line, it's just commented out.

process.StartInfo.RedirectStandardInput = true;

Check this MSDN example for more info.

The way you're writing to StandardInput from the C# side is how I would expect it to work, given this and assuming that you already tried to run your method with process.StartInfo.RedirectStandardInput set to true . So, the only way I could see this not working is if your Python code (which you should attach to the question) wasn't reading stdin properly.

According to this , you can do that by either reading sys.stdin like a file, prompting the user for input or getting command-line arguments. Since you stated that your Python program is currently running, my guess is that you want to use either read or readlines to do that. Note that after you've done that you should uncomment process.StartInfo.RedirectStandardInput = true; .

Consider using CliWrap . It lets you spawn child processes and pipe inputs/outputs in a very expressive way.

You can, for example, pipe from a binary stream:

await using var stream = File.Open("file.bin");
var command = stream | Cli.Wrap("pythonapp").WithArguments("foo bar");

var result = await command.ExecuteAsync();

More info here: https://github.com/Tyrrrz/CliWrap#piping

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM