1

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?

1 Answer 1

4

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()
Sign up to request clarification or add additional context in comments.

5 Comments

My python scripts do not interact with each other, only with the C# portion. Do I need to have/generate a python script which imports everything?
That depends on how they "interact with the C# portion". If the scripts "do something with .NET" as soon as they are loaded they have to be loaded either from .NET or python. Your python scripts might not interact with each other in a runtime-sense, but the classes/types within them depend on each other. Is it possible to split in files containing entry points and library scripts? or having some kind of defined entry function you could call from .net? Then you could just load them all from .net and get the entry functions.
So you are using the classes defined in python from .NET? Or do the scripts represent some kind of extension/plug-in which attach to .NET interfaces/events/.. ? If you just want all the declared modules/classes/functions to be on your scope you could also just do Directory.GetFiles(".", "*.py").ToList().ForEach(f => engine.ExecuteFile(f, scope));.
I'm using the classes defined in python from .NET (Via C#s dynamic keyword). I've replaced my code with yours, but unfortunately, I cannot seem to import the modules (ImportException). They are in a different directory then the binary, in a /script folder.
Then you would have to provide the proper search paths. I added some info to my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.