导入一个不存在的包
importing a package that doesn't exist
我以前从未见过这样的导入问题。我从 site-packages
中删除了一个目录,相应的包仍然可以导入。
python2
> import google
> print(google.__path__)
['/home/bamboo/.local/lib/python2.7/site-packages/google']
然而这个目录实际上并不存在
ls: cannot access /home/bamboo/.local/lib/python2.7/site-packages/google: No such file or directory
我已经删除了所有我知道的与之相关的内容,但一定还有一些东西在附近。
再深入一点,我尝试重新加载 google
。
python2
> import google;
> reload(google);
ImportError: No module named google
很明显它在重新加载时识别出它已经消失了。
查看 sys.modules
你会得到
python2
> import sys
> print(sys.modules)
{'google': <module 'google' (built-in)>, 'copy_reg': <module 'copy_reg' from '/usr/lib/python2.7/copy_reg.pyc'> ...
这表明显然 google
是内置的。
关于动机的说明:通常这种问题会很奇怪,但不会成为阻碍。我的问题是 google
包屏蔽了同名的不同包。
tl,dr: 使用 pip
完全卸载 Google 软件包。
这里有两个问题:
- google 包的奇怪 import/reload 行为
- 删除 google 包
import/reload 行为
我可以通过安装 (Google) protobuf 软件包来重现 import/reload 行为(许多 Google 软件包的行为方式相同)。
$ mktmpenv -p $(which python2)
...
$ python --version
Python 2.7.13
$ pip install protobuf
...
Installing collected packages: six, protobuf
Successfully installed protobuf-3.5.1 six-1.11.0
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>> import sys
>>> print sys.modules['google']
<module 'google' (built-in)>
>>> reload(google)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named google
我怀疑这里发生的事情是 Google 更喜欢将所有 Google 包安装在一个 google
包下,但是这个包不是设计为可导入的,因此意外的重新加载行为。但是按名称导入子包按预期工作:
>>> import protobuf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named protobuf
>>> from google import protobuf
>>> protobuf.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf']
>>> reload(protobuf)
<module 'google.protobuf' from '~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf/__init__.pyc'>
>>>
删除 google 包
问题说明:
I removed a directory from site-packages and the corresponding package is still importable.
这也可以转载:
($ rm -rf ~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google
$ python
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>>
这里的问题是简单地删除 google
目录及其内容不足以完全卸载存在的任何 Google 包。
site-packages 目录仍然包含文件 protobuf-3.5.1-py2.7-nspkg.pth
,其中包含以下代码(为了便于阅读,分成几行,原来是一行分号分隔的语句):
import sys, types, os
has_mfs = sys.version_info > (3, 5)
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',))
importlib = has_mfs and __import__('importlib.util')
has_mfs and __import__('importlib.machinery')
m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])))
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
mp = (m or []) and m.__dict__.setdefault('__path__',[])
(p not in mp) and mp.append(p)
行
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
正在 sys.modules
中创建 google
模块(如果它尚不存在)- 这就是为什么 google
模块即使在目录已被删除后仍可导入的原因。
删除 google
模块的正确方法是使用 pip
:
卸载 google 包
pip uninstall protobuf
如果 pip
在构建环境中不可用,则需要在站点包中识别任何相关文件和文件夹(*dist-info/
、*.pth
)并将其删除手动。
我以前从未见过这样的导入问题。我从 site-packages
中删除了一个目录,相应的包仍然可以导入。
python2
> import google
> print(google.__path__)
['/home/bamboo/.local/lib/python2.7/site-packages/google']
然而这个目录实际上并不存在
ls: cannot access /home/bamboo/.local/lib/python2.7/site-packages/google: No such file or directory
我已经删除了所有我知道的与之相关的内容,但一定还有一些东西在附近。
再深入一点,我尝试重新加载 google
。
python2
> import google;
> reload(google);
ImportError: No module named google
很明显它在重新加载时识别出它已经消失了。
查看 sys.modules
你会得到
python2
> import sys
> print(sys.modules)
{'google': <module 'google' (built-in)>, 'copy_reg': <module 'copy_reg' from '/usr/lib/python2.7/copy_reg.pyc'> ...
这表明显然 google
是内置的。
关于动机的说明:通常这种问题会很奇怪,但不会成为阻碍。我的问题是 google
包屏蔽了同名的不同包。
tl,dr: 使用 pip
完全卸载 Google 软件包。
这里有两个问题:
- google 包的奇怪 import/reload 行为
- 删除 google 包
import/reload 行为
我可以通过安装 (Google) protobuf 软件包来重现 import/reload 行为(许多 Google 软件包的行为方式相同)。
$ mktmpenv -p $(which python2)
...
$ python --version
Python 2.7.13
$ pip install protobuf
...
Installing collected packages: six, protobuf
Successfully installed protobuf-3.5.1 six-1.11.0
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>> import sys
>>> print sys.modules['google']
<module 'google' (built-in)>
>>> reload(google)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named google
我怀疑这里发生的事情是 Google 更喜欢将所有 Google 包安装在一个 google
包下,但是这个包不是设计为可导入的,因此意外的重新加载行为。但是按名称导入子包按预期工作:
>>> import protobuf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named protobuf
>>> from google import protobuf
>>> protobuf.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf']
>>> reload(protobuf)
<module 'google.protobuf' from '~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf/__init__.pyc'>
>>>
删除 google 包
问题说明:
I removed a directory from site-packages and the corresponding package is still importable.
这也可以转载:
($ rm -rf ~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google
$ python
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>>
这里的问题是简单地删除 google
目录及其内容不足以完全卸载存在的任何 Google 包。
site-packages 目录仍然包含文件 protobuf-3.5.1-py2.7-nspkg.pth
,其中包含以下代码(为了便于阅读,分成几行,原来是一行分号分隔的语句):
import sys, types, os
has_mfs = sys.version_info > (3, 5)
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',))
importlib = has_mfs and __import__('importlib.util')
has_mfs and __import__('importlib.machinery')
m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])))
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
mp = (m or []) and m.__dict__.setdefault('__path__',[])
(p not in mp) and mp.append(p)
行
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
正在 sys.modules
中创建 google
模块(如果它尚不存在)- 这就是为什么 google
模块即使在目录已被删除后仍可导入的原因。
删除 google
模块的正确方法是使用 pip
:
pip uninstall protobuf
如果 pip
在构建环境中不可用,则需要在站点包中识别任何相关文件和文件夹(*dist-info/
、*.pth
)并将其删除手动。