python – 导入不存在的包

前端之家收集整理的这篇文章主要介绍了python – 导入不存在的包前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我以前从未见过像这样的导入问题.我从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

我已经删除了我所知道的与之相关的所有内容,但仍然必须有一些东西悬而未决.

挖掘更深层次我尝试重新加载谷歌.

python2
> import google;
> reload(google);
ImportError: No module named google

所以显然它认识到重新加载了.

检查出你得到的sys.modules

python2
> import sys
> print(sys.modules)
{'google': 

这表明谷歌显然是内置的.

关于动机的注意事项:通常这类问题会很奇怪,但不是一个显示限制因素.对我来说问题是谷歌软件包正在掩盖一个不同的同名包.

最佳答案
tl,dr:使用pip完全卸载Google软件包.

这里有两个问题:

> google软件包的奇怪导入/重新加载行为
>删除谷歌包

导入/重新加载行为

我可以通过安装(Google)protobuf软件包重现导入/重新加载行为(许多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']

我怀疑这里发生的是谷歌更喜欢在一个谷歌软件包下安装所有谷歌软件包,但这个软件包不是可导入的,因此意外的重新加载行为.但是,按名称导入子包按预期工作:

>>> import protobuf
Traceback (most recent call last):
  File "

删除谷歌包

问题是:

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或sys.modules.setdefault(‘google’,types.ModuleType(‘google’))

正在sys.modules中创建谷歌模块(如果它尚不存在) – 这就是为什么谷歌模块即使在目录被删除后也可导入.

删除谷歌模块的正确方法是使用pip卸载谷歌软件包:

pip uninstall protobuf

如果构建环境中没有pip,则可以在站点包中识别任何相关文件文件夹(* dist-info /,* .pth)并手动删除它们.

猜你在找的Python相关文章