如果这是一个愚蠢的问题,请提前道歉。总的来说,我是 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/