Gavin Gassmann
Gavin Gassmann

Reputation: 337

Compiling all files C#/IronPython

I'm embedding IronPython into C# as a way to modify the program I am working on. As such, there are multiple files which need to be used at once.

        Code = "";
        Engine = Python.CreateEngine();
        Runtime = Engine.Runtime;
        var files = Directory.GetFiles("script", "*.py", SearchOption.AllDirectories);
        foreach (var tr in files.Select(file => new StreamReader(file)))
        {
            Code += "\n";
            Code += tr.ReadToEnd();
            tr.Close();
        }
        Scope = Engine.CreateScope();

        Engine.CreateScriptSourceFromString(AddImports(Code)).Execute(Scope);

This takes all the files in /script and combines them into a single string to have a script source created from them, this is, of course, a flawed method because if the classes do not inherit in an alphabetical order, an UnboundNameException will occur

class bar(foo):
    pass

class foo():
    pass

How would I go about compiling all of the files in a normal manner?

Upvotes: 1

Views: 1678

Answers (1)

Simon Opelt
Simon Opelt

Reputation: 6201

If you structure your code/files as python modules, import and use them as such, the python runtime will handle/resolve your imports and dependencies. Lets say you have your primary python file containing your main entry point as A.py

import B, C
foo = B.Foo()
bar = C.Bar()

foo.foo()
bar.bar(foo)

print("done")

This file uses the modules B and C defined in B.py and C.py.

B.py:

class Foo:
    def foo(self):
        print("Foo.foo()")

C.py (notice that module C uses/imports module B as well):

import B
class Bar:
    def bar(self, foo):
        print("Bar.bar()")

The .NET boilerplate (assuming that A.py, B.py and C.py reside in the same directory as your .NET binary or on you path) for setting up the engine and executing everything would look like

var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var source = engine.CreateScriptSourceFromFile("A.py");
source.Execute(scope);

Notice that only A.py (as the main entry point) has to be loaded and everything else will be resolved by the runtime.

If your scripts are split into multiple folders you might have to change the search path accordingly. Assuming that all your files except A.py reside in a folder called scripts that could look like

var paths = engine.GetSearchPaths();
paths.Add("scripts");
engine.SetSearchPaths(paths);

Note that if for some reason you would like to avoid module namespacing when using your classes, you could also import *. This might be easier for some use-cases but might create naming clashes (e.g. if both A and B would define a class Foo).

from B import *
from C import *
foo = Foo()
bar = Bar()

Upvotes: 4

Related Questions