imp.find_module 的替代品?
背景
当您使用命名空间包并将代码库划分为单独的文件夹时,我已经厌倦了 pylint 无法导入文件的问题。因此,我开始深入研究 astNG 源代码,该源代码已被确定为问题的根源(请参阅错误报告 8796 on astng)。问题的核心似乎是在查找导入的过程中使用了 python 自己的imp.find_module。
发生的情况是,导入的第一个(子)包 - import abc
中的 a
- 被馈送到带有 None
find_module代码>路径。无论返回的路径是什么,都会被输入到查找循环中的下一个遍中的 find_module
中,您将在上一个示例中尝试查找 b
。
来自 logilab.common.modutils 的伪代码:
path = None
while import_as_list:
try:
_, found_path, etc = find_module(import_as_list[0], path)
#exception handling and checking for a better version in the .egg files
path = [found_path]
import_as_list.pop(0)
问题
这就是问题所在:您只能从 find_module
获得第一个最佳命中,其中可能包含也可能不包含您的子包。如果您没有找到子包,您将无法退出并尝试下一个子包。
我尝试显式使用 sys.path 而不是 None,以便可以从路径列表中删除结果并进行第二次尝试,但是 python 的模块查找器足够聪明,路径中不必完全匹配,使这种方法无法使用 - 无论如何,据我所知。
热泪盈眶的请求
是否有 find_modules 的替代方案,它将返回所有可能的匹配项或采用排除列表?我也愿意接受完全不同的解决方案。最好不要手动修补 python,但这并非不可能 - 至少对于本地解决方案而言。
(买者自负:我正在运行 python 2.6,由于当前公司政策的原因无法升级,对 p3k 等的建议不会被标记为已接受,除非它是唯一的答案。)
Background
I've grown tired of the issue with pylint not being able to import files when you use namespace packages and divide your code-base into separate folders. As such I started digging into the astNG source-code which has been identified as the source of the trouble (see bugreport 8796 on astng). At the heart of the issue seems to be the use of pythons own imp.find_module
in the process of finding imports.
What happens is that the import's first (sub)package - a
in import a.b.c
- is fed to find_module
with a None
path. Whatever path comes back is then fed into find_module
the next pass in the look up loop where you try to find b
in the previous example.
Pseudo-code from logilab.common.modutils:
path = None
while import_as_list:
try:
_, found_path, etc = find_module(import_as_list[0], path)
#exception handling and checking for a better version in the .egg files
path = [found_path]
import_as_list.pop(0)
The Problem
This is what's broken: you only get the first best hit from find_module
, which may or may not have your subpackages in it. If you DON'T find the subpackages, you have no way to back out and try the next one.
I tried explicitly using sys.path instead of None, so that the result could be removed from the path list and a second attempt be made, but python's module finder is clever enough that there doesn't have to be an exact match in the paths, making this approach unusable - to the best of my knowledge anyway.
Teary-eyed Plea
Is there an alternative to find_modules which will return ALL possible matches or take an exclude list? I'm also open to completely different solutions. Preferably not patching python by hand, but it wouldn't be impossible - at least for a local solution.
(Caveat emptor: I'm running python 2.6 and for reasons of current company policy can't upgrade, suggestions for p3k etc won't get marked as accepted unless it's the only answer.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从Python 2.5开始,正确的方法是使用 pkgutil.iter_modules() (对于平面列表)或 pkgutil.walk_packages()< /a> (对于子包树)。两者都与命名空间包完全兼容。
例如,如果我只想查找“jmb”的子包/子模块,我会这样做:
您还可以使用 iter_modules 或 walk_packages 来遍历 sys.path 上的所有模块;有关详细信息,请参阅上面链接的文档。
Since Python 2.5, the right way to do this is with pkgutil.iter_modules() (for a flat list) or pkgutil.walk_packages() (for a subpackage tree). Both are fully compatible with namespace packages.
For example, if I wanted to find just the subpackages/submodules of 'jmb', I would do:
You can also use iter_modules or walk_packages to walk all the modules on sys.path; see the docs linked above for details.
我也厌倦了 PyLint 中的这种限制。
我不知道 imp.find_modules() 的替代品,但我想我找到了另一种方法来处理 PyLint 中的命名空间包。请参阅我对您链接到的错误报告的评论 (http://www.logilab.org/ticket/8796)。
这个想法是使用 pkg_resources 来查找命名空间包。这是我对 logilab.common.modutils._module_file() 的补充,就在
while modpath
之后:这不是很精致,但只处理顶级命名空间包。
I've grown tired of this limitation in PyLint too.
I don't know a replacement for imp.find_modules(), but I think I found another way to deal with namespace packages in PyLint. See my comment on the bug report you linked to (http://www.logilab.org/ticket/8796).
The idea is to use pkg_resources to find namespace packages. Here's my addition to
logilab.common.modutils._module_file()
, just afterwhile modpath
:This not very refined and only handles top-level namespace packages though.
警告+免责声明:尚未测试!
之前:
之后: - 感谢pjeby提及
pkgutil
!warning + disclaimer: not tested yet!
before:
after: - thanks pjeby for mentioning
pkgutil
!