Python 中如何实现自动导入缺失的库?

在编写 Python 项目的时候,我们经常会遇到导入模块失败的错误:

ImportError: No module named 'xxx'或者ModuleNotFoundError: No module named 'xxx'

导入失败,通常分为两种:一种是导入自己写的模块(即以 .py 为后缀的文件),另一种是导入三方库。本文主要讨论第二种情况。

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

一、单个模块中缺失的库

在编写代码的时候,如果我们需要使用某个三方库(如 requests),但不确定实际运行的环境是否装了它,那么可以这样:

try:
    import requests
except ImportError:
    import os
    os.system('pip install requests')
    import requests

这样写的效果是,如果找不到 requests 库,就先安装,再导入。

在某些开源项目中,我们可能还会看到如下的写法(以 json 为例):

try:
    import simplejson as json
except ImportError:
    import json

这样写的效果是,优先导入三方库 simplejson,如果找不到,那就使用内置的标准库 json。

这种写法的好处是不需要导入额外的库,但它有个缺点,即需要保证那两个库在使用上是兼容的,如果在标准库中找不到替代的库,那就不可行了。

如果真找不到兼容的标准库,也可以自己写一个模块(如 my_json.py),实现想要的东西,然后在 except 语句中导入它。

try:
    import simplejson as json
except ImportError:
    import my_json as json

二、整个项目中缺失的库

以上的思路是针对开发中的项目,但是它有几个不足:

  1. 在代码中对每个可能缺失的三方库都 pip install,并不可取;
  2. 某个三方库无法被标准库或自己手写的库替代,该怎么办?
  3. 已成型的项目,不允许做这些修改怎么办?

所以这里的问题是:有一个项目,想要部署到新的机器上,它涉及很多三方库,但是机器上都没有预装,该怎么办?

对于一个合规的项目,按照约定,通常它会包含一个“requirements.txt ”文件,记录了该项目的所有依赖库及其所需的版本号。这是在项目发布前,使用命令pip freeze > requirements.txt 生成的。

使用命令 pip install -r requirements.txt (在该文件所在目录执行,或在命令中写全文件的路径),就能自动把所有的依赖库给装上。

但是,如果项目不合规,或者由于其它倒霉的原因,我们没有这样的文件,又该如何是好?

一个笨方法就是,把项目跑起来,等它出错,遇到一个导库失败,就手动装一个,然后再跑一遍项目,遇到导库失败就装一下,如此循环……

三、自动导入任意缺失的库

有没有一种更好的可以自动导入缺失的库的方法呢?

在不修改原有的代码的情况下,在不需要“requirements.txt”文件的情况下,有没有办法自动导入所需要的库呢?

当然有!先看看效果:

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

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

# 以下代码在 python 3.7.0 版本验证通过
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 ,我们先打印一下,看看它是个什么东西?

 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

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

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

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

  • 可以用 try…except 方式,实现简单的三方库导入或者替换

  • 已知全部缺失的依赖库时(如 requirements.txt),可以手动安装

  • 利用 sys.meta_path,可以自动导入任意的缺失库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/15916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每天一道算法练习题--Day17 第一章 --算法专题 --- ----------布隆过滤器

场景 假设你现在要处理这样一个问题,你有一个网站并且拥有很多访客,每当有用户访问时,你想知道这个 ip 是不是第一次访问你的网站。 hashtable 可以么 一个显而易见的答案是将所有的 IP 用 hashtable 存起来,每次访问都去 hash…

微软开源AI修图工具让老照片重现生机

GitHub - microsoft/Bringing-Old-Photos-Back-to-Life: Bringing Old Photo Back to Life (CVPR 2020 oral) 支持划痕修复,以及模型训练。 Old Photo Restoration (Official PyTorch Implementation) Project Page | Paper (CVPR version) | Paper (Journal vers…

Mysql第二章 多表查询的操作

这里写自定义目录标题 一 外连接与内连接的概念sql99语法实现 默认是内连接sql99语法实现左外连接,把没有部门的员工也查出来sql99语法实现右外连接,把没有人的部门查出来sql99语法实现满外连接,mysql不支持这样写mysql中如果要实现满外连接的…

【Java数据结构】——第九节.向上建堆和向下建堆的区别

作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:Java初阶数据结构 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!! 文章目…

Android jetpack Compose之约束布局

概述 我们都知道ConstraintLayout在构建嵌套层级复杂的视图界面时可以有效降低视图树的高度,使视图树扁平化,约束布局在测量布局耗时上比传统的相对布局具有更好的性能,并且约束布局可以根据百分比自适应各种尺寸的终端设备。因为约束布局确…

下载——安装——使用FinalShell

下载——安装——使用FinalShell FinalShell简介:下载:使用: FinalShell简介: FinalShell是一款免费的国产的集SSH工具、服务器管理、远程桌面加速的软件,同时支持Windows,macOS,Linux&#xf…

No.050<软考>《(高项)备考大全》【冲刺4】《软考之 119个工具 (2)》

《软考之 119个工具 (2)》 21.检查:22.偏差分析:23.滚动式规划:24.紧前关系绘图法(PDM):25.确定依赖关系:26.时间提前量与滞后量:28.发布的估算数据:29.自下而上估算:30.项目管理软件:31.储备分析:32.类比估算:33.参数估算:34.三点估算:35.进度网络分析:…

JS实现拼音(字母)匹配(搜索)汉字(姓名)

这就是个模糊查询,我们平常做的都是直接输入汉字去把对应的值过滤出来,但我还真是第一次通过拼音去查询(当然不只是拼音,汉字也是可以的),以前还真没注意这个。唉,这可咋搞,我怎么知…

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据,你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块,它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中,我们将介绍 statsmodel 库的基础知识、如何…

(七)ArcCatalog应用基础——图层操作与数据输出

(七)ArcCatalog应用基础——图层操作与数据输出 目录 (七)ArcCatalog应用基础——图层操作与数据输出 1.地图与图层操作1.1创建图层1.2设置文件特征1.3保存独立的图层文件 2.地理数据输出2.1输出为Shapefile2.2输出为Coverage2.3属…

笔记本电脑没有声音了怎么恢复

笔记本电脑 在使用的过程中,突然没有声音的话,对于人们来说会很麻烦。那么笔记本电脑没有声音了怎么恢复呢?下面小编为大家整理了笔记本电脑没有声音的恢复方法,一起来看看吧。 方法/步骤: 方法一:网络适配器检查音频…

UE5实现建筑剖切效果

文章目录 1.实现目标2.实现过程2.1 材质参数集2.2 材质遮罩函数2.3 更新Box3.参考资料1.实现目标 基于BoxMask材质节点,在UE5中实现建筑物的剖切效果,GIF动图如下: 2.实现过程 实现原理与之前“BoxMask实现建筑生长效果”的原理相同,都是基于BoxMask材质节点实现。 具体实…

操作系统之内存管理

连续分配 一、单一连续 直接为要运行的进程分配一个内存,只适合单任务,只能用于单对象、单任务,内存被分配为系统区和用户区,系统区在低地址,用户区是一个用户独享 二、等分分区 由于分配一个内存只能执行单任务&a…

MongoDB【常用命令】

目录 1:基本常用命令 1.1:演示案例 1.2:数据库操作 1.2.1:选择和创建数据库,查看当前正在使用的数据库命令 1.2.2:数据库的删除 1.3:集合操作 1.3.1:集合的显式创建&#xff0…

C++ srand()和rand()用法

参考C rand 与 srand 的用法 计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随…

【机器学习】HOG+SVM实现行人检测

文章目录 一、准备工作1. 下载数据集2. 解压数据集 二、HOG特征简介1. 梯度(Gradient)2. 格子(Cell)3. 块归一化(Block Normalization)4. HOG特征(HOG Feature)5. 使用skimage.featu…

docker容器原理及简单且详细的使用

docker原理简单介绍 docker是一种虚拟化容器技术。 虚拟化:早期为了节约成本和学习只有在宿主机中基于 kvm(基于内核的虚拟机)等技术虚拟出来完整的操作系统,而这个完整的操作系统会大量的占用宿主机的硬件资源,当创建…

Oracle LiveLabs实验:DB Security - Data Masking and Subsetting (DMS)

概述 本实验介绍了适用于 Enterprise Manager 的 Oracle 数据屏蔽和子集 (DMS) 包的各种特性和功能。 它使用户有机会学习如何配置这些功能,以便在非生产环境中保护他们的敏感数据。 此实验申请地址在这里,时间为60分钟。 本实验也是DB Security Adva…

无惧黑暗强光,纯视觉导航也能全天候作业

对于一台激光导航扫地机器人而言,全天候作业并非难事,那么纯视觉导航扫地机器人能做到吗? 无论对于人,还是机器人,光线环境的变化对“眼睛”的影响都是致命的。由于视觉传感器对于光线十分敏感,在家庭场景…

linux入门---软硬链接

软链接 使用指令ln -s 被链接的文件 生成的软链接文件 便可以创建软连接文件,ln是link的简写表明当前要创建链接文件,s是soft的简写表明当前创建的链接文件为软链接文件,然后加上被链接的文件,最后写上生成的链接文件的文件名比如…