使用自定义导入程序导入子模块包含&#34; <module>&#34;在find_module fullname参数

时间:2016-01-28 13:27:21

标签: c# python import hook ironpython

目前我正在为Ironpython开发一个自定义导入器,它应该添加一个抽象层来编写自定义导入器。抽象层是一个IronPython模块,它基于PEP 302和IronPython zipimporter模块。架构看起来像这样:

Architexture

为了测试我的导入器代码,我编写了一个带有模块的简单测试包,如下所示:

/Math/
    __init__.py
    /MathImpl/
             __init__.py
             __Math2__.py

/数学/ __ INIT __ PY:

print ('Import: /Math/__init__.py')

/数学/ MathImpl / __ INIT __ PY:

# Sample math package
print ('Begin import /Math/MathImpl/__init__.py')
import Math2
print ('End import /Math/MathImpl/__init__.py: ' + str(Math2.add(1, 2)))

/Math/MathImpl/Math2.py:

# Add two values
def add(x, y):
    return x + y
print ('Import Math2.py!')

如果我尝试在脚本中导入MathImpl这样的import Math.MathImpl

我的genericimporter被调用并在find_module方法中搜索某些模块/包。如果找到则返回导入器的实例,否则返回:

public object find_module(CodeContext/*!*/ context, string fullname, params object[] args)
{
    // Set module
    if (fullname.Contains("<module>"))
    {
        throw new Exception("Why, why does fullname contains <module>?");
    }

    // Find resolver
    foreach (var resolver in Host.Resolver)
    {
        var res = resolver.GetModuleInformation(fullname);

        // If this script could be resolved by some resolver
        if (res != ResolvedType.None)
        {
            this.resolver = resolver;
            return this;
        }
    }
    return null;
}

如果第一次调用find_modulefullname包含Math,这是正常的,因为应先导入Math。第二次调用find_module时,应导入Math.MathImpl,问题在于,fullname现在的值为<module>.MathImpl,而不是Math.MathImpl。< / p>

我的想法是,在导入__name__时未正确设置模块名称(Math),但我在load_module中导入模块时无论如何都设置了此项:< / p>

public object load_module(CodeContext/*!*/ context, string fullname)
{
    string code = null;
    GenericModuleCodeType moduleType;
    bool ispackage = false;
    string modpath = null;
    PythonModule mod;
    PythonDictionary dict = null;

    // Go through available import types by search-order
    foreach (var order in _search_order)
    {
        string tempCode = this.resolver.GetScriptSource(fullname + order.Key);

        if (tempCode != null)
        {
            moduleType = order.Value;
            code = tempCode;
            modpath = fullname + order.Key;

            Console.WriteLine("     IMPORT: " + modpath);

            if ((order.Value & GenericModuleCodeType.Package) == GenericModuleCodeType.Package)
            {
                ispackage = true;
            }

            break;
        }
    }

    // of no code was loaded
    if (code == null)
    {
        return null;
    }

    var scriptCode = context.ModuleContext.Context.CompileSourceCode
        (
            new SourceUnit(context.LanguageContext, new SourceStringContentProvider(code), modpath, SourceCodeKind.AutoDetect),
            new IronPython.Compiler.PythonCompilerOptions() { },
            ErrorSink.Default
        );

    // initialize module
    mod = context.ModuleContext.Context.InitializeModule(modpath, context.ModuleContext, scriptCode, ModuleOptions.None);

    dict = mod.Get__dict__();

    // Set values before execute script
    dict.Add("__name__", fullname);
    dict.Add("__loader__", this);
    dict.Add("__package__", null);

    if (ispackage)
    {
        // Add path
        string subname = GetSubName(fullname);
        string fullpath = string.Format(fullname.Replace(".", "/"));

        List pkgpath = PythonOps.MakeList(fullpath);
        dict.Add("__path__", pkgpath);
    }
    else
    {
        StringBuilder packageName = new StringBuilder();
        string[] packageParts = fullname.Split(new char[] { '/' });
        for (int i = 0; i < packageParts.Length - 1; i++)
        {
            if (i > 0)
            {
                packageName.Append(".");
            }

            packageName.Append(packageParts[i]);
        }

        dict["__package__"] = packageName.ToString();
    }

    var scope = context.ModuleContext.GlobalScope;
    scriptCode.Run(scope);

    return mod;
}

我希望有人知道,为什么会这样。可能导致问题的几行是:

var scriptCode = context.ModuleContext.Context.CompileSourceCode
    (
       new SourceUnit(context.LanguageContext, new SourceStringContentProvider(code), modpath, SourceCodeKind.AutoDetect),
            new IronPython.Compiler.PythonCompilerOptions() { },
            ErrorSink.Default
     );

mod = context.ModuleContext.Context.InitializeModule(modpath, context.ModuleContext, scriptCode, ModuleOptions.None);

因为我不知道,以这种方式创建模块是完全正确的。

可以重现下载此项目/分支:https://github.com/simplicbe/Simplic.Dlr/tree/f_res_noid并开始Sample.ImportResolver的问题。将引发find_module中的例外情况。

谢谢大家!

1 个答案:

答案 0 :(得分:0)

此问题已解决。 Modpath不允许包含/的内容。通常只允许使用字符,也可以使用文件名。

也许这对其他人有帮助......