pythonc#monoreturn-code

Get Python to read a return code from C# in a reliable fashion


I've written a large-ish program in Python, which I need to talk to a smaller C# script. (I realise that getting Python and C# to talk to each other is not an ideal state of affairs, but I'm forced to do this by a piece of hardware, which demands a C# script.) What I want to achieve in particular - the motivation behind this question - is that I want to know when a specific caught exception occurs in the C# script.

I've been trying to achieve the above by getting my Python program to look at the C# script's return code. The problem I've been having is that, if I tell C# to give a return code x, my OS will receive a return code y and Python will receive a return code z. While a given x always seems to correspond to a specific y and a specific z, I'm having difficulty deciphering the relationship between the three; they should be the same.

Here are the specifics of my setup:

And here's a minimal working example of the sort of thing I'm talking about:

This is a tiny C# script:

namespace ConsoleApplication1
{
    class Script
    {
        const int ramanujansNumber = 1729;

        bool Run()
        {
            return false;
        }

        static int Main(string[] args)
        {
            Script program = new Script();
            if(program.Run()) return 0;
            else return ramanujansNumber;
        }
    }
}

If I compile this using mcs Script.cs, run it using mono Script.exe and then run echo $?, it prints 193. If, on the other hand, I run this Python script:

import os

result = os.system("mono Script.exe")
print(result)

it prints 49408. What is the relationship between these three numbers: 1729, 193, 49408? Can I predict the return code that Python will receive if I know what the C# script will return?

Note: I've tried using Environment.Exit(code) in the C# script instead of having Main return an integer. I ran into exactly the same problem.


Solution

  • With os.system the documentation explicitly states that the result is in the same format as for the os.wait, i.e.:

    a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced.

    So in your case it looks like:

    >>> 193<<8
    49408
    

    You might want to change that part to using subprocess, e.g. as in the answer to this question

    UPD: As for the mono return code, it looks like only the lower byte of it is used (i.e. it is expected to be between 0 and 255). At least:

    >>> 1729 & 255
    193