Search Unity

Reading Standard Ouput from a Python App into Unity

Discussion in 'Scripting' started by d_nash, Jul 4, 2017.

  1. d_nash

    d_nash

    Joined:
    Feb 5, 2017
    Posts:
    6
    Hi. I'm trying to integrate a Python app with my Unity project. All I really need to do is be able to read in its standard output into Unity and I'll be able to manipulate it how I need. However I've been struggling with how to do this.

    Here is a script I tried to piece together from an example of the .NET Process.StandardOutput property here :

    Code (csharp):
    1.      void Start () {
    2.         string path = "./example.py";
    3.         print (path);
    4.         process = new System.Diagnostics.Process ();
    5.         process.StartInfo.FileName = path;
    6.         process.StartInfo.UseShellExecute = false;
    7.         process.StartInfo.RedirectStandardOutput = true;
    8.         process.Start ();
    9.         StreamReader reader = process.StandardOutput;
    10.         string str = reader.ReadLine ();
    11.         print (str);
    12.         process.WaitForExit ();
    13.         process.Close ();
    14.     }
    Here is the error I get:
    Code (csharp):
    1.  
    2. Win32Exception: ApplicationName='./example.py', CommandLine='', CurrentDirectory=''
    3. System.Diagnostics.Process.Start_noshell (System.Diagnostics.ProcessStartInfo startInfo, System.Diagnostics.Process process)
    4. System.Diagnostics.Process.Start_common (System.Diagnostics.ProcessStartInfo startInfo, System.Diagnostics.Process process)
    5. System.Diagnostics.Process.Start ()
    6. (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start ()
    7. GameController.Start () (at Assets/GameController.cs:24)
    8.  
    I've had no luck deciphering what this error means. I thought it was to do with the filepath but I've tried every possible permutation of the path to no avail. The python app is right inside my Assets directory so I'm not sure why it wouldn't see it, if that is even the problem.

    Any advice? .NET is really not my area.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    I got this codelet working:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TestSystemProcess : MonoBehaviour
    5. {
    6.     void Start ()
    7.     {
    8.         var p = new System.Diagnostics.Process();
    9.         p.StartInfo.FileName = "testpython.py";
    10.         p.StartInfo.Arguments = "optional arguments separated with spaces";
    11.         p.StartInfo.UseShellExecute = false;
    12.         p.StartInfo.RedirectStandardOutput = true;
    13.         p.Start();  
    14.  
    15.         Debug.Log (p.StandardOutput.ReadToEnd ());
    16.     }
    17. }
    It accepts arguments to the python program, and then captures its stdout and displays it in the Unity debug log.

    Here is the python program:

    Code (csharp):
    1. #!/usr/bin/env python
    2.  
    3. # please be sure to chmod +x me otherwise I won't run!
    4.  
    5. import sys
    6.  
    7. print "Hello, I am the testpython.py python program outputting."
    8. print
    9. print "That was a blank line and here is one more."
    10. print
    11. print "Here are the arguments you passed in:"
    12.  
    13. for arg in sys.argv[1:]:
    14.     print arg
    15.  
    That is on MacOSX though, and I don't have my Windows box handy to test it, but obviously you gotta have Python installed.

    With Windows, you might need to actually specify the command argument as "python yourprogram.py arguments"

    With Windows, I'm not sure what mechanism recognizes a .py file and launches your python interpreter, but on Mac it is explicit within the she-bang line (first line of the program), and the fact that it is marked executable (chmod +x).
     
  3. d_nash

    d_nash

    Joined:
    Feb 5, 2017
    Posts:
    6
    I appreciate the help but even using your code I'm still getting the same error as above. I'm also on MacOS with Python installed and tried using "python example.py" in the command arguments. Have also chmod +x the app.
     
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,448
  5. d_nash

    d_nash

    Joined:
    Feb 5, 2017
    Posts:
    6
    I considered this, but I'm concerned about the latency of outputing to a file from the Python, reading it into Unity, and then applying logic based on that information that affects the gameworld.

    Could this be done in your opinion without any significant input lag?
     
  6. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,448
    i don't think there is noticeable difference to read small text file..(if the current version runs script, waits for script to finish and only then parses that standard output text)

    but i'd use sockets if need to stream data out continuously/faster..
     
  7. d_nash

    d_nash

    Joined:
    Feb 5, 2017
    Posts:
    6
    Yes this whole process would need to happen on every single frame update so maybe sockets is a better direction. Thanks for your help, will continue to investigate this issue.