c# - 使用 IronPython 的无限递归引用

标签 c# python recursion ironpython

如果这是一个愚蠢的问题,请提前道歉。总的来说,我是 Python 的新手(对其他语言根本不是新手),尤其是 IronPython 的新手。

我正在尝试通过我的 C# 项目运行 Python 项目。我将所有相关的 Python 资源作为嵌入式资源包含在内(我将其读入 Dictionary<string,string>,其中键是模块的名称,值是文件的内容。

我已经实现了一个类,与对“Custom IronPython import resolution”的回复中建议的类非常相似,如下所示:

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我从 IronPython Lib 中取出的模块,所以我的 ImportModuleFromResources方法使用第一个 if block 和引用得到解析。

下一次迭代尝试导入 sys (使用 else block 和内置模块导入),然后是 errno (同样是 else block 和内置模块导入)-> nt (再次内置导入)-> nt (再次..) -> ntpath (是的..) -> 然后回到 os再次,并继续进行无限递归以再次遍历模块...(当然会导致堆栈溢出)。

因为我不是 Python 专家,而且我不知道 IronPython 的标准库模块以及它们如何相互引用,所以我确定我做错了一些非常基本的错误,但不确定我需要哪个引用删除、操作我包含的一个 Lib 文件(我认为不太可能),或改进我的 ImportModuleFromResources方法以避免递归引用..

帮助将不胜感激。谢谢!

最佳答案

我已经像Einar Egilsson一样做了已在 Custom IronPython import resolution 中提出=> 使用 PlatformAdaptationLayer

通过这种方式,ironpython 使用自己的机制来搜索模块,并且仅在找不到模块时才使用您的代码。

关于c# - 使用 IronPython 的无限递归引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20890935/

相关文章:

python - 插入值时如何存储dict的差异?

c# - 使用 oledb netting "_xlnm#_FilterDatabase"作为工作表名称的多工作表导入

c# - 在调用基本构造函数之前计算值

Python Pyspark : Filter for 1 Day Before Current Date Using F. current_date()

python - 在 gui 中更新 matplotlib 图的有效方法?

php - 基于一个或多个提供的键递归访问潜在的嵌套值

c# - 打印总和为特定值的所有子集

c# - 如何返回 C# 方法调用的语法上下文

c# - 如何重新创建app.config.exe.config

python - 无法在pycharm中运行jupyter