简体   繁体   English

C#和IronPython集成

[英]C# and IronPython integration

I want simply use io.py from C# to write a file and I use the following code: 我想简单地使用C#中的io.py来编写文件,我使用以下代码:

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' Microsoft.CSharp.RuntimeBinder.RuntimeBinderException告诉没有writelines的重载接受参数'1'

it seems like that method doesn't exists... but into io.py documentation it exists. 似乎该方法不存在......但是在io.py文档中它存在。

PS The same is for close method!!! PS同样是close方法!

Any idea? 任何的想法?

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). 我只能告诉你如何使你的代码工作,但是我对IronPython没有多少经验,也不知道为什么这样做(虽然我试着去了解)。 First, it seems io module is treated in a special way and there is special (non-dynamic) class for that. 首先,似乎io模块以特殊方式处理,并且有特殊的(非动态)类。 When you do io.open what is returned is instance of PythonIOModule._IOBase class. 当你执行io.open返回的是PythonIOModule._IOBase类的实例。 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. 并且亲眼看看“writeline”方法(这是常规方法,而不是动态方法)接受CodeContext实例作为第一个参数,第二个参数是行。 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. 有趣的是,这个类本身已经包含了CodeContext的字段,但是由于某种原因它是内部的,更糟糕​​的是 - writelines(和其他方法)本来可以使用CodeContext而不需要我们提供外部的。 Why is it done like this - I have no idea. 为什么这样做 - 我不知道。

So to make your code working, we have to get CodeContext somewhere. 因此,为了使您的代码正常工作,我们必须在某处获得CodeContext。 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM