当前位置: 首页 > 后端技术 > Python

如何在python中自动导入缺失的库?

时间:2023-03-26 16:11:23 Python

作者:猫下豌豆花来源:Python猫在写python项目的时候,我们可能经常会遇到导入模块失败的错误:ImportError:Nomodulenamed'xxx'或者ModuleNotFoundError:Nomodulenamed'xxx'。导入失败的问题通常分为两种:一种是导入自己写的模块(即.py后缀的文件),另一种是导入第三方库。本文主要讨论第二种情况,以后我们会详细讨论其他相关话题。解决导入Python库失败问题的关键是在运行环境中安装缺少的库(注意是否是虚拟环境),或者使用合适的替代方案。这个问题分为三种情况:1.单个模块中缺少库在写代码的时候,如果我们需要用到第三方库(比如requests),但是在实际运行中不确定是否安装了环境,那么我们可以这样:try:importrequestsexceptImportError:importosos.system('pipinstallrequests')importrequests这样写的效果是如果找不到requests库,先安装再安装导入它。在一些开源项目中,我们可能还会看到如下写法(以json为例):try:importsimplejsonasjsonexceptImportError:importjson这种写法的效果是先导入三方库simplejson。如果找不到,则使用内置的标准库json。这种写法的好处是不需要导入额外的库,但是有一个缺点,就是需要保证两个库在使用上是兼容的。如果在标准库中找不到替代库,那是行不通的。如果实在找不到兼容的标准库,也可以自己写一个模块(比如my_json.py),实现自己想要的,然后在except语句中导入。try:importsimplejsonasjsonexceptImportError:importmy_jsonasjson2.整个项目缺少库上面的思路针对的是正在开发的项目,但是有几个缺点:1.在代码中检查每一个三方库可能缺少不建议使用pipinstall;2.第三方库不能用标准库或手写库代替,怎么办?3.完成的项目不允许做这些修改怎么办?所以这里的问题是:有一个项目我想部署到一台新机器上。它涉及到很多第三方库,但没有一个是预装在机器上的。我应该怎么办?对于一个合规的项目,按照惯例,通常会包含一个“requirements.txt”文件,里面记录了项目所有的依赖库及其需要的版本号。这是在项目发布之前使用命令pipfreeze>requirements.txt生成的。使用命令pipinstall-rrequirements.txt(在文件所在目录下执行,或者在命令中写上整个文件的路径),即可自动安装所有依赖库。但是,如果项目不合规,或者由于其他一些不幸的原因,我们没有这样的文件怎么办?比较笨的办法是运行工程,等它报错,遇到库引导失败就手动安装一个,然后再运行工程,库引导失败就安装,以此类推。。。(此处省略1千句脏话)...3.自动导入任何缺失的库。有没有更好的方法来自动导入缺失的库?有没有办法在不修改原代码的情况下,不用“requirements.txt”文件,自动导入需要的库呢?当然有!先来看看效果:我们以龙卷风为例。我们从第一步可以看出我们没有安装tornado。第二步之后,当我们再次导入tornado时,程序会自动帮我们下载并安装tornado,这样就不会再报错了。autoinstall是我们手写的模块,代码如下:以下代码已经在python3.6.1版本验证通过target=None):如果路径为None且名称不在cls._loaded:cls._loaded.add(name)print("Installing",name)try:result=os.system('pipinstall{}'.format(name))ifresult==0:returnimport_module(name)exceptExceptionase:print("Failed",e)returnNonesys.meta_path.append(AutoInstall)这段代码使用了sys.meta_path,我们先打印一下看是否它是什么?Python3的import机制在搜索过程中大致是这样的顺序:在sys.modules中搜索,它缓存了所有导入的模块;在sys.meta_path中搜索,支持自定义加载器在sys.path中搜索,它记录了目录某些库所在的名称。如果未找到,则抛出ImportError异常。需要注意的是,sys.meta_path在不同的Python版本中是不同的。例如,它在Python2和Python3中非常不同;在较新的Python3版本(3.4+)中,自定义加载器需要实现find_spec方法,而较早的版本使用find_module。上述代码是一个自定义的类库加载器AutoInstall,可以实现自动导入三方库的目的。需要说明的是,该方法会“劫持”所有新导入的库,破坏原有的导入方法,因此也可能会出现一些奇怪的问题,请注意。sys.meta_path是Python探针的一个应用程序。探针,或者说导入钩子,在Python中是一个几乎不被人注意的机制,但是它可以做很多事情,比如加载网络上的库,导入时修改模块,自动安装缺少的库,上传审计信息,延迟加载等限于篇幅,我们不再详细展开。最后总结一下:可以使用try...except方法实现简单的三方库导入或者替换所有已知缺失的依赖库(如requirements.txt),可以手动安装使用sys.meta_path,也可以自动导入任何缺失的库引用信息:https://github.com/liuchang08...http://blog.konghy.cn/2016/10...https://docs.python.org/3/lib。..