美文网首页
[转][Python] 如何实现自动导入缺失的库?

[转][Python] 如何实现自动导入缺失的库?

作者: 棘刺 | 来源:发表于2020-02-12 14:08 被阅读0次

    注:
    以下文章来源于Python猫 ,作者豌豆花下猫。
    仅供学习,若侵权,即删。
    链接:由浅入深:Python 中如何实现自动导入缺失的库?

    正文:

    在写 Python 项目的时候,我们可能经常会遇到导入模块失败的错误:ImportError: No module named 'xxx'或者ModuleNotFoundError: No module named 'xxx'。

    导入失败问题,通常分为两种:一种是导入自己写的模块(即以 .py 为后缀的文件),另一种是导入三方库。本文主要讨论第二种情况,今后有机会,我们再详细讨论其它的相关话题。

    解决导入 Python 库失败的问题,其实关键是在运行环境中装上缺失的库(注意是否是虚拟环境),或者使用恰当的替代方案。

    自动导入任意缺失的库:

    效果:


    image

    我们以 tornado 为例,第一步操作可看出,我们没有装过 tornado,经过第二步操作后,再次导入 tornado 时,程序会帮我们自动下载并安装好 tornado,所以不再报错。

    autoinstall 是我们手写的模块,代码如下:

    # 以下代码在 python 3.6.1 版本验证通过
    import sys
    import os
    from importlib import import_module
    
    
    class AutoInstall():
        _loaded = set()
    
        @classmethod
        def find_spec(cls, name, path, target=None):
                if path is None and name not in cls._loaded:
                    cls._loaded.add(name)
                    print("Installing", name)
                    try:
                        result = os.system('pip install {}'.format(name))
                        if result == 0:
                            return import_module(name)
                    except Exception as e:
                        print("Failed", e)
                return None
    
    sys.meta_path.append(AutoInstall)
    

    这段代码中使用了sys.meta_path ,我们先打印一下,看看它是个什么东西?


    image

    Python 3 的 import 机制在查找过程中,大致顺序如下:

    • 在 sys.modules 中查找,它缓存了所有已导入的模块
    • 在 sys.meta_path 中查找,它支持自定义的加载器
    • 在 sys.path 中查找,它记录了一些库所在的目录名
    • 若未找到,抛出ImportError异常

    其中要注意,sys.meta_path 在不同的 Python 版本中有所差异,比如它在 Python 2 与 Python 3 中差异很大;在较新的 Python 3 版本(3.4+)中,自定义的加载器需要实现find_spec方法,而早期的版本用的则是find_module。


    image

    以上代码是一个自定义的类库加载器 AutoInstall,可以实现自动导入三方库的目的。需要说明一下,这种方法会“劫持”所有新导入的库,破坏原有的导入方式,因此也可能出现一些奇奇怪怪的问题,敬请留意。

    sys.meta_path 属于 Python 探针的一种运用。探针,即import hook,是 Python 几乎不受人关注的机制,但它可以做很多事,例如加载网络上的库、在导入模块时对模块进行修改、自动安装缺失库、上传审计信息、延迟加载等等。

    限于篇幅,我们不再详细展开了。最后小结一下:

    • 可以用 try…except 方式,实现简单的三方库导入或者替换
    • 已知全部缺失的依赖库时(如 requirements.txt),可以手动安装
    • 利用 sys.meta_path,可以自动导入任意的缺失库

    参考资料:
    https://github.com/liuchang0812/slides/tree/master/pycon2015cn
    http://blog.konghy.cn/2016/10/25/python-import-hook
    https://docs.python.org/3/library/sys.html#sys.meta_path

    作者:豌豆花下猫
    来源:Python猫

    相关文章

      网友评论

          本文标题:[转][Python] 如何实现自动导入缺失的库?

          本文链接:https://www.haomeiwen.com/subject/gxxcfhtx.html