导入挂钩的 Ironpython 问题 subpackage/submodule
Ironpython issue with import hook subpackage/submodule
我一直在努力解决我现在认为可能是 IronPython 中的错误的问题。如果有人能证实这个怀疑或纠正我的错误,我将不胜感激。
我面临的问题是在尝试使用 sys.meta_path 或 sys.path_hooks 应用导入挂钩时。在导入简单的模块和包时,IronPython 似乎正确地调用了我的钩子。如果我尝试导入一个子模块或包,例如 foo.bar,则会调用挂钩来导入 foo,但在尝试导入 bar 时不会调用挂钩。
我创建了以下代码来重现该问题。当 运行 在 CPython 中时,同样的代码不会遇到任何问题。
import imp
import sys
class ReflectiveLoader2(object):
def __init__(self):
print "Init RL2"
def find_module(self, fullname, path=None):
print "find_module_RL2 called with fullname %s and path %s" % (fullname, path)
self.path = path
return self
def load_module(self, fullname):
print "load_module_RL2 called with fullname %s" % fullname
mod = imp.new_module(fullname)
mod.__name__ = fullname
mod.__loader__ = self
#Simulate a couple scenarios for imports
#Simulate a method
if fullname == "foo":
print "its foo"
mod.__filepath__ = r"C:\not\a\real\path\foo.py"
source = "def fooFunction(thing):print thing*3"
#Simulate another method
elif fullname == "bar":
print "its bar"
mod.__filepath__ = r"C:\not\a\real\path\bar.py"
source = "def barFunction(thing):print thing*4"
#Simulate package
elif fullname == "baz":
print "its baz"
mod.__filepath__ = r"C:\not\a\real\path\baz\__init__.py"
mod.__path__ = r"C:\not\a\real\path\baz"
source = "print 'initializing baz stuff here'"
#Simulate subpackage
elif fullname == "baz.bat":
print "its baz.bat"
mod.__filepath__ = r"C:\not\a\real\path\baz\bat.py"
mod.__path__ = r"C:\not\a\real\path\baz"
source = "def Batfunc():print 'in baz.bat sub package'"
#catchall
else:
print "Not foo, bar or baz its %s" % fullname
source = ""
exec source in mod.__dict__
return mod
sys.meta_path = [ReflectiveLoader2()]
import foo
foo.fooFunction("ABC")
import bar
bar.barFunction("DEF")
import baz.bat
baz.bat.Batfunc()
这是使用 IronPython 和 CPython 的上述代码的输出。我在两个独立的系统上有 运行 这段代码,以防其中一个系统安装错误
C:\Users\Administrator\project>"C:\Program Files (x86)\IronPython 2.7\ipy.exe" ReflectiveLoader2.py
Init RL2
find_module_RL2 called with fullname foo and path None
load_module_RL2 called with fullname foo
its foo
ABCABCABC
find_module_RL2 called with fullname bar and path None
load_module_RL2 called with fullname bar
its bar
DEFDEFDEFDEF
find_module_RL2 called with fullname baz and path None
load_module_RL2 called with fullname baz
its baz
initializing baz stuff here
Traceback (most recent call last):
File "ReflectiveLoader2.py", line 63, in <module>
ImportError: No module named bat
C:\Users\Administrator\project>C:\Python27\python.exe ReflectiveLoader2.py
Init RL2
find_module_RL2 called with fullname foo and path None
load_module_RL2 called with fullname foo
its foo
ABCABCABC
find_module_RL2 called with fullname bar and path None
load_module_RL2 called with fullname bar
its bar
DEFDEFDEFDEF
find_module_RL2 called with fullname baz and path None
load_module_RL2 called with fullname baz
its baz
initializing baz stuff here
find_module_RL2 called with fullname baz.bat and path C:\not\a\real\path\baz
load_module_RL2 called with fullname baz.bat
its baz.bat
in baz.bat sub package
编辑:
我忘了说我试过研究其他人是否有这个问题,我能找到的最接近的是 post
https://mail.python.org/pipermail/ironpython-users/2012-April/015879.html
据我所知,没有采取任何措施来解决所报告的问题
经过一些额外的故障排除后,我认为这主要是操作员错误。看起来 CPython 在模块的路径属性方面稍微宽容一些。如果把上面的代码改成
mod.__path__ = r"C:\not\a\real\path\baz"
看起来像
mod.__path__ = [r"C:\not\a\real\path\baz",]
一切正常。
如果有人有足够的动力为 IronPython 创建类似的类型检查,我在 IronPython 源文件 IronPython\Runtime\Importer.cs 的第 151 和 120 行附近发现了不检查列表类型的代码,如下所示
object path;
List listPath;
if (scope.__dict__._storage.TryGetPath(out path) && (listPath = path as List) != null) {
return ImportNestedModule(context, scope, new [] {name}, 0, listPath);
}
如果将 __path__ 设置为字符串(代替预期的列表),则转换为列表会失败,并且永远不会调用 ImportNestedModule。
CPython 和 IronPython 之间的不一致问题已经解决
https://github.com/IronLanguages/main/issues/1202
我一直在努力解决我现在认为可能是 IronPython 中的错误的问题。如果有人能证实这个怀疑或纠正我的错误,我将不胜感激。
我面临的问题是在尝试使用 sys.meta_path 或 sys.path_hooks 应用导入挂钩时。在导入简单的模块和包时,IronPython 似乎正确地调用了我的钩子。如果我尝试导入一个子模块或包,例如 foo.bar,则会调用挂钩来导入 foo,但在尝试导入 bar 时不会调用挂钩。
我创建了以下代码来重现该问题。当 运行 在 CPython 中时,同样的代码不会遇到任何问题。
import imp
import sys
class ReflectiveLoader2(object):
def __init__(self):
print "Init RL2"
def find_module(self, fullname, path=None):
print "find_module_RL2 called with fullname %s and path %s" % (fullname, path)
self.path = path
return self
def load_module(self, fullname):
print "load_module_RL2 called with fullname %s" % fullname
mod = imp.new_module(fullname)
mod.__name__ = fullname
mod.__loader__ = self
#Simulate a couple scenarios for imports
#Simulate a method
if fullname == "foo":
print "its foo"
mod.__filepath__ = r"C:\not\a\real\path\foo.py"
source = "def fooFunction(thing):print thing*3"
#Simulate another method
elif fullname == "bar":
print "its bar"
mod.__filepath__ = r"C:\not\a\real\path\bar.py"
source = "def barFunction(thing):print thing*4"
#Simulate package
elif fullname == "baz":
print "its baz"
mod.__filepath__ = r"C:\not\a\real\path\baz\__init__.py"
mod.__path__ = r"C:\not\a\real\path\baz"
source = "print 'initializing baz stuff here'"
#Simulate subpackage
elif fullname == "baz.bat":
print "its baz.bat"
mod.__filepath__ = r"C:\not\a\real\path\baz\bat.py"
mod.__path__ = r"C:\not\a\real\path\baz"
source = "def Batfunc():print 'in baz.bat sub package'"
#catchall
else:
print "Not foo, bar or baz its %s" % fullname
source = ""
exec source in mod.__dict__
return mod
sys.meta_path = [ReflectiveLoader2()]
import foo
foo.fooFunction("ABC")
import bar
bar.barFunction("DEF")
import baz.bat
baz.bat.Batfunc()
这是使用 IronPython 和 CPython 的上述代码的输出。我在两个独立的系统上有 运行 这段代码,以防其中一个系统安装错误
C:\Users\Administrator\project>"C:\Program Files (x86)\IronPython 2.7\ipy.exe" ReflectiveLoader2.py
Init RL2
find_module_RL2 called with fullname foo and path None
load_module_RL2 called with fullname foo
its foo
ABCABCABC
find_module_RL2 called with fullname bar and path None
load_module_RL2 called with fullname bar
its bar
DEFDEFDEFDEF
find_module_RL2 called with fullname baz and path None
load_module_RL2 called with fullname baz
its baz
initializing baz stuff here
Traceback (most recent call last):
File "ReflectiveLoader2.py", line 63, in <module>
ImportError: No module named bat
C:\Users\Administrator\project>C:\Python27\python.exe ReflectiveLoader2.py
Init RL2
find_module_RL2 called with fullname foo and path None
load_module_RL2 called with fullname foo
its foo
ABCABCABC
find_module_RL2 called with fullname bar and path None
load_module_RL2 called with fullname bar
its bar
DEFDEFDEFDEF
find_module_RL2 called with fullname baz and path None
load_module_RL2 called with fullname baz
its baz
initializing baz stuff here
find_module_RL2 called with fullname baz.bat and path C:\not\a\real\path\baz
load_module_RL2 called with fullname baz.bat
its baz.bat
in baz.bat sub package
编辑: 我忘了说我试过研究其他人是否有这个问题,我能找到的最接近的是 post
https://mail.python.org/pipermail/ironpython-users/2012-April/015879.html
据我所知,没有采取任何措施来解决所报告的问题
经过一些额外的故障排除后,我认为这主要是操作员错误。看起来 CPython 在模块的路径属性方面稍微宽容一些。如果把上面的代码改成
mod.__path__ = r"C:\not\a\real\path\baz"
看起来像
mod.__path__ = [r"C:\not\a\real\path\baz",]
一切正常。
如果有人有足够的动力为 IronPython 创建类似的类型检查,我在 IronPython 源文件 IronPython\Runtime\Importer.cs 的第 151 和 120 行附近发现了不检查列表类型的代码,如下所示
object path;
List listPath;
if (scope.__dict__._storage.TryGetPath(out path) && (listPath = path as List) != null) {
return ImportNestedModule(context, scope, new [] {name}, 0, listPath);
}
如果将 __path__ 设置为字符串(代替预期的列表),则转换为列表会失败,并且永远不会调用 ImportNestedModule。
CPython 和 IronPython 之间的不一致问题已经解决 https://github.com/IronLanguages/main/issues/1202