Как опубликовать модуль "__main__" при хостинге IronPython 2.0? - PullRequest
2 голосов
/ 27 января 2011

Я пытаюсь добавить функциональность [rlcompleter][1] к моему форку IronTextBoxControl2 в RevitPythonShell .

Однако у меня возникли серьезные проблемы с линией:

import __main__

в rlcompleter.py. Это потому, что у меня нет такого модуля. Я искал / просматривал кодовую базу IronPython 2.0, пытаясь выяснить, как опубликовать модуль.

Кажется, я могу сделать это из экземпляра IronPython.Runtime.PythonContext с помощью метода PublishModule(string name, PythonModule module). Но у меня возникли проблемы со следующим:

  • получение PythonContext экземпляра
  • получение PythonModule экземпляра

Что у меня есть , это ScriptEngine и ScriptScope. Я бы хотел, чтобы область была опубликована в виде модуля __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 ]

2 голосов
/ 18 мая 2011

Я столкнулся с той же проблемой. Я пытался использовать ScriptEngine.Execute * для запуска кода. Оказывается, используя ScriptEngine.CreateScriptSourceFromFile, а затем вызов ExecuteProgram решает проблему.

Проверьте следующее для полного решения: проблема при выполнении юнит-тестов Selenium Python в C # с ScriptEngine (.NET 3.5)

Примечание: IronPython 2.7 делает все это проще:

public void SetupEnvironment(ScriptEngine engine, out ScriptScope scope)
{
    scope = IronPython.Hosting.Python.CreateModule(engine, "__main__");
    return;
} 
1 голос
/ 28 января 2011

Неважно, я просмотрел исходный код IronPython 2.0.3 и придумал следующее:

  • a PythonContext является Microsoft.Scripting.Runtime.LanguageContext
  • языковой контекст ScriptEngine можно получить с помощью метода Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(ScriptEngine)
  • если у вас есть ScriptEngine для python, тогда вы можете просто разыграть.

Ничего себе. Так что теперь у меня наконец есть мой PythonContext! Поэтому я позвоню CreateModule и PublishModule и буду дома перед чаем!

Подождите. Во-первых, второй аргумент 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 довольно сложным для понимания и часто путаюсь с тем, что и где определено.

...