python - 导入一个不存在的包

标签 python python-2.7 python-import

我以前从未见过这样的导入问题。我从 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 package 正在掩盖同名的不同包。

最佳答案

tl,博士:使用 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']
    <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'>
    >>> 
    

    删除谷歌包

    问题指出:

    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'))
    正在创建 google sys.modules 中的模块如果它不存在 - 这就是 google 的原因即使目录已被删除,模块仍可导入。

    删除google的正确方法模块是通过使用 pip 卸载谷歌包:
    pip uninstall protobuf
    如果 pip在构建环境中不可用,这是在站点包中识别任何相关文件和文件夹( *dist-info/*.pth )并手动删除它们的情况。

    关于python - 导入一个不存在的包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48102783/

    相关文章:

    Python装饰器记录器

    python - 按表格格式化列表数据

    python - pytest从不同的测试文件独立导入同一模块

    python - 为什么在 Windows 上的 Python 3 下创建模块后导入失败?

    python - 导入错误 : No module named <something>

    python - 如何删除或禁用 Jupyter 笔记本中的 ipywidgets 小部件清除按钮?

    python - Django ORM 查询 : getting "has many" relation objects

    python - 如果不满足条件如何跳到下一行?

    python - 关于 python 中 x < y <= z 的混淆

    python - 如何循环遍历 Pandas Dataframe 中的数字列并过滤值?