简而言之,这怎么会发生?

cternus@astarael:~⟫ python
Python 2.7.12 (default, Jun 29 2016, 14:05:02)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import backports
>>> import imp
>>> imp.find_module('backports')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named backports

imp 模块声称是“用于实现导入语句的机制的接口(interface)”。如果是这样, 为什么 import 语句可以找到 backports ,而 imp.find_module() 不能?

对于一些背景:backports 声称是一个“命名空间包”,而不是一个包本身;其他模块,例如 backports.shutil_get_terminal_size ,位于此命名空间中。这构成了 an ultimately-rejected PEP 的基础。我问这个问题是因为我有一个 this issue 的变体,我正在努力寻找原因。

更多奇怪之处:
>>> backports.__file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__file__'
>>> dir(backports)
['__doc__', '__name__', '__path__']
>>> backports.__path__
['/Library/Python/2.7/site-packages/backports']
>>> import os; os.path.exists(backports.__path__[0])
False

(不,我的系统上的任何地方都没有名为 backportsbackports.py 的文件或目录。)

编辑以澄清 :我知道这可能代表我的系统的一个奇怪的配置状态。我的问题不是“我该如何解决这个问题”,而是“这怎么可能?”

最佳答案

该模块可以通过 python-configparser APT 包带来。



这是可能的,因为 python-configparser 使用了 路径配置文件 (.pth 文件):

[email protected]:/# dpkg -L python-configparser | head | tail -n 1
/usr/lib/python2.7/dist-packages/configparser-3.5.0b2-nspkg.pth

这个文件在解释器启动时会被 python 的 站点 模块自动获取,因为它位于 /usr/lib/python2.7/dist-packages/ 并且具有 .pth 扩展名。作为 docs say :



文件 /usr/lib/python2.7/dist-packages/configparser-3.5.0b2-nspkg.pth 包含以下内容:
import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('backports', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('backports', [os.path.dirname(p)])));m = m or sys.modules.setdefault('backports', types.ModuleType('backports'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)

So, this code is auto-executed on python startup. Slightly beautified, it looks like this:

import sys, types, os

has_mfs = sys.version_info > (3, 5)

p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',))
importlib = has_mfs and __import__('importlib.util')
has_mfs and __import__('importlib.machinery')

m = has_mfs and sys.modules.setdefault('backports', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('backports', [os.path.dirname(p)])))

m = m or sys.modules.setdefault('backports', types.ModuleType('backports'))

mp = (m or []) and m.__dict__.setdefault('__path__',[])

(p not in mp) and mp.append(p)

它的作用(至少在 python 2 上)是:它 手动 通过调用 types.ModuleType 构造函数创建一个模块对象(这就是为什么它看起来像 <module 'backports' (built-in)> )并将其放入 sys.modulessys.modules.setdefault('backports', types.ModuleType('backports')) 。将其添加到 sys.modules 后, import backports 将只返回该对象。
__path__ 给出提示
[email protected]:/# python -c 'import backports; print backports.__path__'
['/usr/lib/python2.7/dist-packages/backports']
[email protected]:/# dpkg -S /usr/lib/python2.7/dist-packages/backports
python-configparser: /usr/lib/python2.7/dist-packages/backports



在Ubuntu上,如上所示,这个包带来了/usr/lib/python2.7/dist-packages/backports,所以我不确定你为什么没有它。也许它是另一个在 MacOS 上表现相似/变体的软件包不同/您只是在调试问题时删除了该目录?

关于python - 什么时候可以 import 找到一个模块,而其他什么都找不到?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38912409/

10-13 02:17