繁体   English   中英

通过全名实例化模块中的python类

[英]Instantiating a python class from a module by full name

我需要创建一个python类的实例并将其存储在C#变量中。 该过程的输入数据是完整的模块名称和类名称。 我正在尝试使用以下方法:

// Here's a sample input:
var moduleName = "sp.content.abilities.torpedo"
var className = "AbilityTorpedo"

// Here's my module loading and class instaitiation
var moduleScope = ScriptEngine.ImportModule(moduleName);
var scriptClass = moduleScope.GetVariable(className);
return ScriptEngine.Operations.CreateInstance(scriptClass);

我的文件夹结构如下所示,并将“脚本”目录添加为IronPython的搜索路径之一( torpedo.py确实包含AbilityTorpedo类):

Scripts
│   .editorconfig
│   __main__.py
│                                       
└───sp                                                               
    │   __init__.py                                              
    │                                         
    └───content                                                                    
        │   __init__.py               
        │                                     
        └───abilities                         
                torpedo.py                    
                __init__.py

当运行列出的实例化方法时, moduleScope.GetVariable(className); 行失败,但以下异常:

'ObjectDictionaryExpando' object has no attribute 'AbilityTorpedo'

调试时,我注意到ImportModule操作返回了从名称的第一部分加载的模块,同时还加载了整个模块层次结构(例如,标记为红色的content模块) 来自调试的moduleScope内容

我有一种适当的方式来按模块的全名加载模块,而不是遍历作用域以查找所需的类吗?

我设法编写了一个扩展类,该类将提供与常规python的“ from X import Y”类似的功能。 最后,我必须使用默认的ImportModule来导入模块层次结构的根,然后遍历结构以找到所需的模块:

private static PythonModule TraverseDown(PythonModule module, string moduleName)
{
    return (PythonModule) module.Get__dict__()[moduleName];
}

private static PythonModule TraverseToTarget(ScriptScope scope, string moduleName)
{
    // The root of the module was already imported by the engine's import module call. 
    var moduleNameParts = moduleName.Split('.').Skip(count: 1).ToList();
    var rootModule = scope.GetVariable<PythonModule>(moduleNameParts.First());
    return moduleNameParts.Skip(count: 1).Aggregate(rootModule, TraverseDown);
}

public static dynamic ImportFromModule(this ScriptEngine engine, string moduleName, string targetImport)
{
    var rootModuleScope = engine.ImportModule(moduleName);
    var targetModule = TraverseToTarget(rootModuleScope, moduleName);
    return targetModule.Get__dict__()[targetImport];
}

这是应该使用此扩展的方式:

// Here's a sample input:
var moduleName = "sp.content.abilities.torpedo"
var className = "AbilityTorpedo"

// Here's my module loading and class instaitiation
var moduleScope = ScriptEngine.ImportFromModule(moduleName, className);
return ScriptEngine.Operations.CreateInstance(scriptClass);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM