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