如果这是一个愚蠢的问题,请提前抱歉。我是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
块并且引用得到解析。
下一次迭代尝试导入sys
(使用else
块和内置模块导入),然后errno
(再次else
块和内置-in module import) - &gt; nt
(再次内置导入) - &gt; nt
(再次......) - &gt; ntpath
(是的..) - &gt;然后再次返回os
,继续无限递归再次通过模块......(当然会导致堆栈溢出)。
由于我不是Python专家,而且我不了解IronPython的标准库模块以及它们如何相互引用,我确信我做的是一些非常基本的错误,但不确定我需要哪些参考取出,操纵我包含的一个Lib文件(不太可能,我认为),或改进我的ImportModuleFromResources
方法以避免递归引用..
非常感谢帮助。谢谢!
答案 0 :(得分:0)
我的做法与Einar Egilsson =&gt;中Custom IronPython import resolution已消化的方式相同使用PlatformAdaptationLayer
通过这种方式,ironpython使用自己的机制来搜索模块,并且只在找不到模块时才使用你的代码。