什么时候可以导入查找模块?

问题描述 投票:2回答:1

简而言之,这怎么可能发生?

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模块声称是“用于实现import语句的机制的接口”。如果是这样,为什么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 python-2.7
1个回答
1
投票

该模块可以通过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

路径配置文件是一个文件,其名称的格式为name.pth,并且存在于上述四个目录之一中......执行以import(后跟空格或制表符)开头的行。

文件/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)

所以,这段代码是在python启动时自动执行的。略微美化,它看起来像这样:

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.modules将它放到sys.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

我没有名为backports的文件或目录

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

© www.soinside.com 2019 - 2024. All rights reserved.