自定义IronPython导入分辨率 [英] Custom IronPython import resolution

查看:145
本文介绍了自定义IronPython导入分辨率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从数据库加载IronPython脚本并执行它。这适用于简单的脚本,但导入是一个问题。如何拦截这些导入调用,然后从数据库加载相应的脚本?

I am loading an IronPython script from a database and executing it. This works fine for simple scripts, but imports are a problem. How can I intercept these import calls and then load the appropriate scripts from the database?

编辑:我的主应用程序是用C#编写的,我想拦截调用在没有编辑Python脚本的情况下在C#端。

My main application is written in C# and I'd like to intercept the calls on the C# side without editing the Python scripts.

编辑:从我所做的研究来看,创建自己的PlatformAdaptationLayer看起来就是你的方式>假设来实现这一点,但在这种情况下它不起作用。我已经创建了自己的PAL,在我的测试中,我的 FileExsists 方法会在脚本中的每次导入时被调用。但由于某种原因,它从不调用 OpenInputFileStream 方法的任何重载。通过IronPython源,一旦FileExists返回true,它就会尝试在路径上找到文件本身。所以这看起来像死路一条。

From the research I've done, it looks like creating your own PlatformAdaptationLayer is the way you're supposed to to implement this, but it doesn't work in this case. I've created my own PAL and in my testing, my FileExsists method gets called for every import in the script. But for some reason it never calls any overload of the OpenInputFileStream method. Digging through the IronPython source, once FileExists returns true, it tries to locate the file itself on the path. So this looks like a dead end.

推荐答案

经过大量的反复试验后,我找到了解决方案。我从未设法让 PlatformAdaptationLayer 方法正常工作。它在尝试加载模块时从未回调过PAL。

After a great deal of trial and error, I arrived at a solution. I never managed to get the PlatformAdaptationLayer approach to work correctly. It never called back to the PAL when attempting to load the modules.

所以我决定使用SetVariable方法替换内置的import函数,如图所示下面(引擎和范围是受保护的成员,为父脚本公开 ScriptEngine ScriptScope ):

So what I decided to do was replace the built-in import function by using the SetVariable method as shown below (Engine and Scope are protected members exposing the ScriptEngine and ScriptScope for the parent script):

delegate object ImportDelegate(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple);

protected void OverrideImport()
{
    ScriptScope scope = IronPython.Hosting.Python.GetBuiltinModule(Engine);
    scope.SetVariable("__import__", new ImportDelegate(DoDatabaseImport));
}

protected object DoDatabaseImport(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple)
{
    if (ScriptExistsInDb(moduleName))
    {
        string rawScript = GetScriptFromDb(moduleName);
        ScriptSource source = Engine.CreateScriptSourceFromString(rawScript);
        ScriptScope scope = Engine.CreateScope();
        Engine.Execute(rawScript, scope);
        Microsoft.Scripting.Runtime.Scope ret = Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetScope(scope);
        Scope.SetVariable(moduleName, ret);
        return ret;
     }
     else
     {   // fall back on the built-in method
         return IronPython.Modules.Builtin.__import__(context, moduleName);
     }
}

希望这有助于某人!

这篇关于自定义IronPython导入分辨率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆