0

We have a C# module that needs to pass XML as a string to a python module and get the process result from that python module (has complicated logic and many imported libraries). But somehow I got nothing returned after several tries, the following is my sample code. Also is that possible to use pyinstaller to package the python module into EXE and achieve same functionality?

    public InquiryResponse ProcessXML(string xml)
    {
        ProcessStartInfo psi = new ProcessStartInfo();
        psi.FileName = @"C:\Python\python.exe";

        psi.Arguments = string.Format(@"C:\myapp.py" {0}", xml);

        psi.UseShellExecute = false;
        psi.CreateNoWindow = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;

        var error = "";
        var result = "";

        using (var process = Process.Start(psi))
        {
            error = process.StandardError.ReadToEnd();
            result = process.StandardOutput.ReadToEnd();
        }

        // Some other process
    }
Kuku
  • 484
  • 8
  • 28
  • Both languages are crossplatform. If you compile Python into a binary it becomes platform dependent. So personally I would advise against that idea. I'm not too familiar with C# to give you an educated answer but I'd try to execute a simple hello world python script and post any error that shows why it doesn't manage to do so. – Tin Nguyen Apr 06 '20 at 12:35
  • 1
    You are not waiting for the python to complete and you have to make sure you read all the data before the python closes. So you first have to wait for a terminating character in the result. You can add a null ('\0'). Then you have to send a command to python to terminate or dispose the process. You can't close the python script until c# reads all the data, otherwise, the stream (StandardOutput) will close. – jdweng Apr 06 '20 at 12:37
  • @jdweng I tried but just realized maybe there is some kind of buffer size? As the XML we generated is huge. If I truncated the returning XML it is fine. I will keep digging – Kuku Apr 07 '20 at 06:42
  • Then do not use ReadToEnd(). StandardOutput is a steam. So use XmlReader.Create(process.StandardOutput). The use code like following : https://stackoverflow.com/questions/40456446/efficient-way-to-read-large-xml-into-dfferent-node-types-in-c-sharp – jdweng Apr 07 '20 at 07:50
  • @jdweng I tried but still no luck. Think it might because our XML contains some Chinese characters. – Kuku Apr 07 '20 at 10:45
  • Can you pass the python the filename instead of the file? With XmlReader will give error with unicode so you need to skip the first line that has utf-8. StreamReader sReader = new StreamReader("firlename"); sReader.ReadLine(); XmlReader reader = XmlReader.Create(sReader); – jdweng Apr 07 '20 at 12:09
  • @jdweng Somehow it still returning nothing when the XML string including Unicode. As a workaround, I need to call the escape Unicode method on the python side. Thanks for the help, really help me a lot. One last question, if we need to pass a very Large XML from C# to python. What will be the best way? – Kuku Apr 08 '20 at 08:50
  • Just pass the filename. – jdweng Apr 08 '20 at 12:07
  • @jdweng the XML is generated by the .net code and pass as a parameter to the python module for further processing. Is this possible ? – Kuku Apr 08 '20 at 23:33
  • Your arguments are wrong : psi.Arguments = string.Format(@"C:\myapp.py" {0}", xml); Do you want to save the xml to a file or pass as standard input to the python? Right now {0} is a filename. The python is the executable in the process and you want to the standardinput (not standardoutput) to be the xml. – jdweng Apr 09 '20 at 00:46
  • @jdweng Thanks for pointing that out. Now I just leave the python script in argument. And put start.RedirectStandardInput = true; Call process.StandardInput.WriteLine(xml); process.StandardInput.Flush(); in python I set a variable to accept the standard input. However the chinese character passed into python 3 module will become '?'. Tried to wrap the standardInput inside StreamWriter: StreamWriter writer= new StreamWriter(process.StandardInput.BaseStream, Encoding.Unicode); Still got no luck. So I have to do the unescape the Chinese character to Unicode string to be the workaround. – Kuku Apr 09 '20 at 10:57
  • I think the question mark is just the way it is being displayed in debugger. The question mark could be the wrong encoding being used or the wrong font. – jdweng Apr 09 '20 at 11:51

0 Answers0