Бесконечная рекурсивная ссылка с использованием IronPython

Извините заранее, если это глупый вопрос. Я новичок в Python вообще (совсем не новичок в других языках) и новичок в IronPython в частности.

Я пытаюсь запустить проект Python через мой C# проект. Я включаю все соответствующие источники Python в качестве встроенных ресурсов (которые я прочитал в Dictionary<string,string> где ключ - это имя модуля, а значение - содержимое файла.

Я реализовал класс, очень похожий на класс, предложенный в этом ответе на " Пользовательское разрешение импорта IronPython", например:

public class PythonInstance
{
    private ScriptEngine engine;
    private ScriptScope scope;
    private ScriptSource source;
    private CompiledCode compiled;
    private object pythonClass;
    private delegate object ImportDelegate(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple);
    private Dictionary<string, string> importModulesCode = new Dictionary<string, string>();

    public PythonInstance(string code, Dictionary<string,string> modulesCode, string className = "PyClass")
    {
        this.importModulesCode.Clear();
        foreach(KeyValuePair<string,string> module in modulesCode)
            this.importModulesCode.Add(module.Key, module.Value);

        //creating engine and stuff
        this.engine = Python.CreateEngine();
        this.scope = Python.GetBuiltinModule(engine);//engine.CreateScope();

        this.scope.SetVariable("__import__", new ImportDelegate(this.ImportModuleFromResources));

        //loading and compiling code
        this.source = this.engine.CreateScriptSourceFromString(code, SourceCodeKind.Statements);
        this.compiled = this.source.Compile();

        //now executing this code (the code should contain a class)
        this.compiled.Execute(this.scope);

        //now creating an object that could be used to access the stuff inside a python script
        this.pythonClass = this.engine.Operations.Invoke(this.scope.GetVariable(className));
    }

    public void SetVariable(string variable, dynamic value)
    {
        this.scope.SetVariable(variable, value);
    }

    public dynamic GetVariable(string variable)
    {
        return this.scope.GetVariable(variable);
    }

    public void CallMethod(string method, params dynamic[] arguments)
    {
        this.engine.Operations.InvokeMember(this.pythonClass, method, arguments);
    }

    public dynamic CallFunction(string method, params dynamic[] arguments)
    {
        return this.engine.Operations.InvokeMember(this.pythonClass, method, arguments);
    }

    protected object ImportModuleFromResources(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple)
    {
        if ((this.importModulesCode.Keys.Contains(moduleName)) && (!string.IsNullOrWhiteSpace(this.importModulesCode[moduleName])))
        {
            string rawScript = this.importModulesCode[moduleName];
            this.engine.Execute(rawScript, this.scope);
            Scope ret = HostingHelpers.GetScope(this.scope);
            this.scope.SetVariable(moduleName, ret);
            return ret;
        }
        else
        {   // fall back on the built-in method
            return Builtin.__import__(context, moduleName);
        }
    }
}

Теперь это, кажется, работает нормально. Просто я получаю исключение переполнения стека при попытке запустить код Python, поскольку ссылки кажутся рекурсивными.

Мой основной файл pyw содержит следующий заголовок:

import os, sys, getopt, __builtin__
from pyglossary.glossary import confPath, VERSION

Первый импорт os модуль, который я взял из Lib IronPython, так что мой ImportModuleFromResources метод использует первый if блок и ссылка будет решена.

Следующая итерация пытается импортировать sys (с использованием else блок и встроенный модуль импорта), затем errno (опять else блок и встроенный модуль импорта) -> nt (снова встроенный импорт) -> nt (снова..) -> ntpath (да..) -> затем возвращаясь к os снова и продолжает бесконечную рекурсию для повторного прохождения модулей... (что, конечно, приводит к переполнению стека).

Так как я не эксперт по Python, и я не знаю ни о стандартных модулях библиотеки IronPython, ни о том, как они ссылаются друг на друга, я уверен, что делаю что-то очень неправильное, но не уверен, какую ссылку мне нужно извлечь, манипулировать одним из моих включенных файлов Lib (вряд ли, я думаю) или улучшить мой ImportModuleFromResources метод, чтобы избежать рекурсивной ссылки.

Помощь будет принята с благодарностью. Спасибо!

1 ответ

Я сделал это так же, как Эйнар Эгильссон предложил в разрешении импорта Custom IronPython => Использовать PlatformAdaptationLayer

Таким образом, Ironpython использует свои собственные механизмы для поиска модулей и использует ваш код только тогда, когда модуль не может быть найден.

Другие вопросы по тегам