2

I have been working on a problem for a while now which I cannot seem to resolve so I need some help! The problem is that I am writing a program in C# but I require a function from a Python file I created. This in itself is no problem:

...Usual Stuff

using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting; 

namespace Program
{
    public partial class Form1 : Form
    {
        Microsoft.Scripting.Hosting.ScriptEngine py;
        Microsoft.Scripting.Hosting.ScriptScope s;
        public Form1()
        {
            InitializeComponent();

            py = Python.CreateEngine(); // allow us to run ironpython programs
            s = py.CreateScope(); // you need this to get the variables

        }

        private void doPython()
        {
            //Step 1: 
            //Creating a new script runtime             
            var ironPythonRuntime = Python.CreateRuntime();

            //Step 2:
            //Load the Iron Python file/script into the memory
            //Should be resolve at runtime
             dynamic loadIPython = ironPythonRuntime.;

             //Step 3:
             //Invoke the method and print the result
             double n = loadIPython.add(100, 200);
             numericUpDown1.Value = (decimal)n;
         }
    }
}

However, this requires for the file 'first.py' to be wherever the program is once compiled. So if I wanted to share my program I would have to send both the executable and the python files which is very inconvenient. One way I thought to resolve this is by adding the 'first.py' file to the resources and running from there... but I don't know how to do this or even if it is possible.

Naturally the above code will not work for this as .UseFile method takes string arguments not byte[]. Does anyone know how I may progress?

  • 1
    One has to ask why you can't just write an equivalent function in C#. Translate the Python, so to speak. – ArtOfCode Dec 27 '14 at 00:53
  • What is the function your trying to call in python, and whats so special about it, is large and complicated? – TheGeneral Dec 27 '14 at 00:57
  • http://stackoverflow.com/questions/15470090/run-exe-file-as-an-embedded-resource-in-c-sharp?rq=1 have all info you need... (If you are not against reading original documentation/support articles - - http://support.microsoft.com/kb/319292) – Alexei Levenkov Dec 27 '14 at 02:08
  • 2
    I tried to do that, but I didn't write the python code (which is rough and uncommented) and having spent the last few days trying to rewrite in c# has not worked out. Despite the fact that I believe I understand what the python code does and that I understand python syntax well enough to translate it, I get similar but different results. Not only that but computation time is far slower in the c# version. I also thought it was an interesting technical exercise. – Alexander Gheorghiu Dec 27 '14 at 12:39

1 Answers1

3

Lets start with the simplest thing that could possibly work, you've got some code that looks a little like the following:

// ...
py = Python.CreateEngine(); // allow us to run ironpython programs
s = py.CreateScope(); // you need this to get the variables
var ironPythonRuntime = Python.CreateRuntime();
var x = py.CreateScriptSourceFromFile("SomeCode.py");
x.Execute(s);
var myFoo = s.GetVariable("myFoo");
var n = (double)myFoo.add(100, 200);
// ...

and we'd like to replace the line var x = py.CreateScriptSourceFromFile(... with something else; If we could get the embedded resource as a string, we could use ScriptingEngine.CreateScriptSourceFromString().

Cribbing this fine answer, we can get something that looks a bit like this:

string pySrc;

var resourceName = "ConsoleApplication1.SomeCode.py";
using (var stream = System.Reflection.Assembly.GetExecutingAssembly()
                          .GetManifestResourceStream(resourceName))
using (var reader = new System.IO.StreamReader(stream))
{
    pySrc = reader.ReadToEnd();
}
var x = py.CreateScriptSourceFromString(pySrc);
Community
  • 1
  • 1
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • Thank you for your reply, sadly I could not get your code to work for me, I replaced "SomeCode.py" with my "first.py" and "myFoo" with "add" which is the function name in "first.py" which I would like to call. The code doesn't throw and error but only return 'null' and I don't know why. Have I missed somthing? – Alexander Gheorghiu Dec 27 '14 at 12:42
  • Did you embed the python file in your assembly? Do you have the right name for that embedded resource? This is not as easy to guess as you might think. – SingleNegationElimination Dec 27 '14 at 14:32
  • I know and I thank you for your time. I found that it doesn't like reading fileName.py, but has no problem reading fileName on its own. Doing this has meant that your first set of instructions worked fine. – Alexander Gheorghiu Dec 27 '14 at 20:51