托管IronPython 2.0时如何发布模块“__main__”?

时间:2011-01-27 16:12:19

标签: c# hosting ironpython

我正在尝试将[rlcompleter][1]功能添加到IronTextBoxControl2RevitPythonShell的分支中。

然而,我遇到了这条线的麻烦:

import __main__
rlcompleter.py中的

。这是因为我没有这样的模块。我一直在搜索/筛选IronPython 2.0代码库,试图找出如何发布模块。

我似乎可以使用方法IronPython.Runtime.PythonContextPublishModule(string name, PythonModule module)的实例执行此操作。但我遇到以下问题:

  • 获取PythonContext实例
  • 获取PythonModule实例

拥有,是ScriptEngineScriptScope。我希望将范围作为模块__main__发布。据我所知,范围已经附加到模块,但我无法弄清楚如何访问它。

以下是代码中我要将它们结合在一起的要点:

    /// <summary>
    /// Set up an IronPython environment - for interactive shell or for canned scripts
    /// </summary>
    public void SetupEnvironment(ScriptEngine engine, ScriptScope scope)
    {                        
        // add variables from Revit
        scope.SetVariable("__revit__", _commandData.Application);
        scope.SetVariable("__commandData__", _commandData);
        scope.SetVariable("__message__", _message);
        scope.SetVariable("__elements__", _elements);
        scope.SetVariable("__result__", (int)Result.Succeeded);                        

        // add preconfigures variables
        scope.SetVariable("__vars__", RevitPythonShellApplication.GetVariables());

        /* register scope as __main__ module here?! */         

        // add the search paths
        AddSearchPaths(engine);
    }

2 个答案:

答案 0 :(得分:2)

我遇到了同样的问题。我试图使用ScriptEngine.Execute *来运行代码。原来使用ScriptEngine.CreateScriptSourceFromFile,然后调用ExecuteProgram解决了这个问题。

查看以下完整解决方案:trouble executing Selenium python unittests in C# with ScriptEngine (.NET 3.5)

注意:IronPython 2.7使整个过程变得更容易:

public void SetupEnvironment(ScriptEngine engine, out ScriptScope scope)
{
    scope = IronPython.Hosting.Python.CreateModule(engine, "__main__");
    return;
} 

答案 1 :(得分:1)

没关系,我浏览了IronPython 2.0.3源代码并提出了以下内容:

  • PythonContextMicrosoft.Scripting.Runtime.LanguageContext
  • 可以通过ScriptEngine方法
  • 获取Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(ScriptEngine)的语言背景
  • 如果你有一个ScriptEngine的python,那么你就可以施展。

哇。所以现在我终于有了PythonContext!所以我打电话给CreateModulePublishModule,然后回家喝茶!

等待。不。首先,CreateModule的第二个参数是Microsoft.Scripting.Runtime.Scope。我们只有一个Microsoft.Scripting.Hosting.ScriptScope。这恰好包含Scope,但其访问者为internal。所以我们需要先做一些反思。

以下是我提出的解决方案增强的示例代码:

/// <summary>
/// Set up an IronPython environment - for interactive shell or for canned scripts
/// </summary>
public void SetupEnvironment(ScriptEngine engine, ScriptScope scriptScope)
{
    // add variables from Revit
    scriptScope.SetVariable("__revit__", _commandData.Application);
    scriptScope.SetVariable("__commandData__", _commandData);
    scriptScope.SetVariable("__message__", _message);
    scriptScope.SetVariable("__elements__", _elements);
    scriptScope.SetVariable("__result__", (int)Result.Succeeded);           

    // add preconfigures variables
    scriptScope.SetVariable("__vars__", RevitPythonShellApplication.GetVariables());

    // add the current scope as module '__main__'
    var languageContext = Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(engine);
    var pythonContext = (IronPython.Runtime.PythonContext)languageContext;
    var module = pythonContext.CreateModule(null, GetScope(scriptScope), null, IronPython.Runtime.ModuleOptions.None);            
    pythonContext.PublishModule("__main__", module);

    // add the search paths
    AddSearchPaths(engine);
}

/// <summary>
/// Be nasty and reach into the ScriptScope to get at its private '_scope' member,
/// since the accessor 'ScriptScope.Scope' was defined 'internal'.
/// </summary>
private Microsoft.Scripting.Runtime.Scope GetScope(ScriptScope scriptScope)
{
    var field = scriptScope.GetType().GetField(
        "_scope", 
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    return (Microsoft.Scripting.Runtime.Scope) field.GetValue(scriptScope);
}

我故意将所有名称空间保留在类型中。我发现IronPython代码很难遵循,并且常常对定义的内容感到困惑。