Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# and IronPython integration

Tags:

c#

ironpython

I want simply use io.py from C# to write a file and I use the following code:

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

System.IO.Directory.SetCurrentDirectory(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) +
"\IronPython\Lib");

ScriptRuntime py = Python.CreateRuntime();
dynamic io = py.UseFile("io.py");
dynamic f = io.open("tmp.txt", "w");

f.writelines("some text...");
f.close();

but when I run the program the runtime give me a:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException telling that no overload of writelines accept argument '1'

it seems like that method doesn't exists... but into io.py documentation it exists.

P.S. The same is for close method!!!

Any idea?

like image 756
xdevel2000 Avatar asked Nov 28 '25 14:11

xdevel2000


1 Answers

I can only tell you how to make your code working, however I don't have much experience with IronPython and have no idea why it is done this way (though I try to learn that). First, it seems io module is treated in a special way and there is special (non-dynamic) class for that. When you do io.open what is returned is instance of PythonIOModule._IOBase class. You can do

var f = (PythonIOModule._IOBase) io.open("tmp.txt", "w");

And see for yourself that "writeline" method (which is regular method, not a dynamic one) accepts CodeContext instance as first argument, and second argument is lines. Interesting that this class itself already contains field with that CodeContext, but it is made internal for some reason, and what is even worse - writelines (and other methods) could have been using that CodeContext and not require us to provide external one. Why is it done like this - I have no idea.

So to make your code working, we have to get CodeContext somewhere. One way is do that via reflection:

var context = (CodeContext) f.GetType().GetField("context", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(f);

Another way is to craft it yourself:

var languageContext = HostingHelpers.GetLanguageContext(engine);
var context = new ModuleContext(io._io, new PythonContext(languageContext.DomainManager, new Dictionary<string, object>())).GlobalContext;

Both methods will work and program will successfully write to a file. Full working sample:

static void Main(string[] args) {                        
    System.IO.Directory.SetCurrentDirectory(@"G:\Python27\Lib");
    var engine = Python.CreateEngine();            
    dynamic io = engine.ImportModule("io");            
    var  f = (PythonIOModule._IOBase) io.open("tmp.txt", "w");
    var languageContext = HostingHelpers.GetLanguageContext(engine);
    var context = new ModuleContext(io._io, new PythonContext(languageContext.DomainManager, new Dictionary<string, object>())).GlobalContext;            
    f.writelines(context, "some text....");
    f.close(context);
}
like image 93
Evk Avatar answered Dec 01 '25 04:12

Evk