导入一个不存在的包

时间:2018-01-04 20:06:09

标签: python python-2.7 python-import

我之前从未见过像这样的导入问题。我从NSData *imageFileData = UIImageJPEGRepresentation(info[UIImagePickerControllerOriginalImage], 0.5); [self.currentChannel sendFileMessageWithBinaryData:imageFileData filename:@"image.jpg" type:@"image/jpg" size:[imageFileData length] data:nil completionHandler:^(SBDFileMessage * _Nullable fileMessage, SBDError * _Nullable error) { }]; 删除了一个目录,相应的包仍可导入。

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包正在掩盖一个不同的同名包。

1 个答案:

答案 0 :(得分:3)

tl,dr:使用pip完全卸载Google软件包。

这里有两个问题:

  • 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']
<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软件包

问题陈述:

  

我从site-packages中删除了一个目录,相应的包仍然是可导入的。

这也可以转载:

($ 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'))

正在google中创建sys.modules模块,如果它尚未存在 - 这就是google模块即使在目录被删除后也可导入的原因。

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

pip uninstall protobuf

如果构建环境中pip不可用,则会在网站包中识别任何相关文件和文件夹(*dist-info/*.pth)并手动删除它们。