目前我正在为Ironpython开发一个自定义导入程序,它应该为编写自定义导入程序添加一个抽象层。抽象层是一个IronPython模块,它基于PEP 302和IronPython zipimporter
模块。架构如下所示:
为了测试导入程序代码,我编写了一个带有模块的简单测试包,如下所示:
/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!')
如果我尝试像这样在脚本中导入MathImpl
:import Math.MathImpl
调用Mygenericimporter
get并在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
中的异常。你知道吗
谢谢大家!你知道吗
这个问题解决了。
Modpath
不允许包含/
的内容。通常只允许字符,也可以在文件名中。你知道吗也许这对其他人有帮助。。。你知道吗
相关问题 更多 >
编程相关推荐