使用自定义导入器导入子模块时,find\u module fullname param中包含“<module>”

2024-09-30 08:31:13 发布

您现在位置:Python中文网/ 问答频道 /正文

目前我正在为Ironpython开发一个自定义导入程序,它应该为编写自定义导入程序添加一个抽象层。抽象层是一个IronPython模块,它基于PEP 302和IronPython zipimporter模块。架构如下所示:

Architexture

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

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

/Math/\uuu init\uuuuuuuuy.py:

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

/Math/MathImpl/\uuu init\uuuuuuuuy.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!')

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

调用Mygenericimporterget并在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_module,则fullname包含Math,这是可以的,因为Math应该首先导入。第二次调用find_module时,应该导入Math.MathImpl,这里的问题是,fullname现在的值是<module>.MathImpl,而不是Math.MathImpl。你知道吗

我的想法是,在导入Math时,模块名(__name__)设置不正确,但在任何情况下,在load_module中导入模块时,我都会设置此名称:

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中的异常。你知道吗

谢谢大家!你知道吗


Tags: 模块pynewstringifinitcontextmath
1条回答
网友
1楼 · 发布于 2024-09-30 08:31:13

这个问题解决了。Modpath不允许包含/的内容。通常只允许字符,也可以在文件名中。你知道吗

也许这对其他人有帮助。。。你知道吗

相关问题 更多 >

    热门问题