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

查看:20
本文介绍了自定义 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 方法替换内置导入函数(Engine 和 Scope 是保护成员,暴露了 ScriptEngineScriptScope 用于父脚本):

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);
     }
}

希望这对某人有所帮助!

Hope this helps someone!

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

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