ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【Python3基础】14-模块、包与虚拟环境

2026/10/1 17:10:47 拓冰建站 浏览量
【Python3基础】14-模块、包与虚拟环境 ▒ 目录 ▒ 导读本篇知识路线1️⃣ 自定义模块如何自己定义模块包2️⃣ 模块路径搜索模块路径搜索规则模块路径搜索注意事项3️⃣ 如何安装第三方模块Python 直接安装使用 easy\_install 安装使用 pip 安装4️⃣ 虚拟环境安装和使用 virtualenv项目开发中使用虚拟环境注意事项5️⃣ 推荐的项目环境操作 文章小结 导读当代码不再只有一个文件模块边界、导入路径和依赖隔离就会直接影响项目能否稳定运行。本篇从自定义模块和包讲起说明 Python 如何搜索模块再介绍第三方模块安装与虚拟环境。原文保留了部分早期工具的使用背景新项目应优先使用 Python 自带的venv创建环境并通过python -m pip调用当前解释器对应的包管理工具。本篇知识路线项目目录 ├─ .venv/ 独立解释器与依赖 ├─ app/ 自己的包 │ ├─ __init__.py │ └─ main.py └─ requirements.txt import ──► 当前目录 / 环境 / 模块搜索路径1️⃣ 自定义模块在项目开发过程中我们经常把项目中常用的功能或算法写成一个可供其它文件调用的函数或类我们把这些函数和类放在一个文件中这个文件就叫做模块因为这个模块是我们自己写的所以叫自定义模块。模块很好的解决了软件工程中的低耦合高内聚的要求我们在项目开发中把经常被使用的函数和类封装成模块是个很好的编程习惯。如何自己定义模块我们自己写个函数放在一个后缀名为 py 的文件里如果我们在其它文件中使用该文件这个文件相对使用它的文件就叫自定义模块。 自定义模块的引用方式是用 import… 或者 from…import… 但要注意自定义的模块和引用文件要放在一个目录下。下面我们实现一个定义模块模块文件名为 mabs.py我们通常叫模块名为 myabs不带后缀名在该模块内我们实现一个函数 myabsfunc该函数返回数字的绝对值我们在 hello.py 文件中引用该自定义模块。 myabs.py 文件该文件为自定义模块 myabs 。 该模块有一个函数 myabsfunc。 defmyabsfunc(data):try:dataint(data)except:raiseTypeError(必须为数字类型)returndataifdata0else-data hello.py 文件。 该文件引用自定义模块 myabs。 importmyabs# 导入自定义模块print(myabs.myabsfunc(-250))当然我们也可以直接导入这个模块内的函数。 hello.py 文件。 该文件引用自定义模块 myabs。 frommyabsimportmyabsfunc# 从自定义模块 myabs 里导入函数print(myabsfunc(-250))我们可以给 import… 后面的名字起个别名。 hello.py 文件。 该文件引用自定义模块 myabs。 frommyabsimportmyabsfuncasabsfunc# 给函数起个别名print(absfunc(-250))################################ 我是分割线 ################################ hello.py 文件。 该文件引用自定义模块 myabs。 importmyabsasabsmodule# 给函数起个别名print(absmodule.myabsfunc(-250))包在开发项目中我们可能要写很多模块为了方便与组织我们可以把这些模块放入一个目录中Python 对按目录来组织模块的方法称为包Package包是模块的集合比模块又高一级的封装。 没有比包更高级别的封装但是包可以嵌套包就像文件目录一样。导入包的方式和导入模块一样但要注意包里面必须要有一个init.py 文件否则会报错。比如在项目 python_one 中我们创建一个 mytools 包把 myabs 模块放入该包中在 hello.py 中使用该包中的 myabsfunc 函数。如果我们的包中有多个比如几十个模块对每个模块都需要使用 from…import… 的方式导入那就很 low 了。Python 支持用 from…import * 的方式可以导入init.py 的文件里的all变量里面限定的模块。假如我们的 mytools 包里面有两个模块 myabs 和 myhaha我们可以在init.py 里面限定要导入的模块。 __init__.py 文件。 变量 __all__ 的值是对使用 from...import * 语法导入模块的限定。 __all__ [myhaha] # 如果使用 from...import * 语法则只导入了 myhaha 模块。 myabs.py 文件该文件为自定义模块 myabs 。 该模块有一个函数 myabsfunc。 defmyabsfunc(data):try:dataint(data)except:raiseTypeError(必须为数字类型)returndataifdata0else-data myhaha.py 文件该文件为自定义模块 myhaha 。 该模块有一个函数 myhahafunc。 defmyhahafunc():returnhaha hello.py 文件。 该文件使用 mytools 包。 frommytoolsimport*# 只导入了 __init__.py 文件里的 __all__ 变量里面的模块。print(myhaha.myhahafunc())# 正确print(myabs.myabsfunc(-250))# 错误当然如果不使用 from…import * 的方式导入模块则不受init.py 文件里的all变量的限制。 比如我们在init.py 文件里写入__all__ [myhaha]我们可以直接导入 myabs 模块。 hello.py 文件。 该文件使用 mytools 包。 frommytoolsimportmyabsprint(myabs.myabsfunc(-250))# 正确不受 __all__ 变量的限制无论是导入包还是模块还是模块里的函数变量或类等等import 后面的内容必须是一级单位。 hello.py 文件。 该文件使用 mytools 包。 importmytools# 正确导入 mytools 包frommytoolsimportmyabs# 正确导入 mytools 包里的 myabs 模块frommytools.myabsimportmyabsfunc# 正确导入 mytools 包里的 myabs 模块里的 myabsfunc 函数importmytools.myabs# 错误import 后面必须是一级单位frommytoolsimportmyabs.myabsfunc# 错误import 后面必须是一级单位2️⃣ 模块路径搜索我们上一节学习如何自定义模块无论是自定义模块还是内建模块还是第三方模块都是模块他们的导入方法都是一样的唯一的区别只是在于他们所在的路径不同。模块路径搜索规则大家注意下面在描述中我们为了表达方便把被导入的包模块函数类等等统称为模块 在导入模块自定义模块内建模块第三方模块具有一样的路径搜索规则时不管在程序中执行了多少次 import该模块只会被导入一次。 这样可以防止程序重复导入模块节省内存和计算资源。那么当使用 import… 语句的时候Python 解释器是怎样找到对应的模块呢Python 会根据 sys.path 的设置按顺序搜索模块我们可以打印出 sys.path。 hello.py 文件。 importmytools# mytools 包在 sys.path 列表中的路径下frommytoolsimportmyabs# 先找到 mytools 包再从 mytools 包下找到 myabs 模块frommytools.myabsimportmyabsfunc# 先找到 mytools 包再从 mytools 包下找到 myabs 模块再从 myabs 模块里找到 myabsfunc 函数importsys# 内建模块 sys该模块在 sys.path 列表中的路径下print(sys.path)我们在 hello.py 文件中打印出了 sys.path 的路径也就是说我们在该文件中引用的模块必须在这些路径下直接或通过 from…间接找到否则就找不到模块。 上面的三种导入方法import mytoolsfrom mytools import myabs,from mytools.myabs import myabsfunc对于 import 导入的模块我们总是能直接或间接通过 from…找到所以我们在 hello.py 中可以找到我们导入的模块。但是我们在项目开发过程中有时候我们的模块所放在的位置有时候并不在 sys.path 列表中那我们如何导入该模块呢比如我们不想通过 mytools 间接导入 myabs 模块我们想直接通过 import 导入 myabs 模块我们只需要把 myabs 模块所在目录加入到 sys.path 列表中即可。 hello.py 文件。 importsys sys.path.append(E:\\python_one\\mytools)# 添加字符串 E:\\python_one\\mytools 到 sys.path 中print(sys.path)importmyabs# 直接导入 myabs 模块print(myabs.myabsfunc(-250))用绝对路径的方式在项目开发过程中一般是不允许的比如我们在本机上开发项目完成后上传到服务器上 项目程序所在服务器的盘符和我们本机的盘符不是一个名称比如我们开发的时候把项目放在本机的 E 盘而服务器上项目在 C 盘大家可能会想我们开放的时候保持和服务器盘符一样不就可以了吗那如果我们的服务器是 linux 呢linux 系统没有盘符的概念。我们使用相对路径是解决以上问题最好的方法。 hello.py 文件。 importsysimportos thisfilepathos.path.abspath(__file__)# hello.py 文件全路径thisfilediros.path.dirname(thisfilepath)# hello.py 所在文件夹全路径mytoolspathos.path.join(thisfiledir,mytools)# mytools 文件夹全路径sys.path.append(mytoolspath)# 添加 mytoolspath 所在全路径到 sys.path 中print(sys.path)importmyabs# 直接导入 myabs 模块print(myabs.myabsfunc(-250))模块路径搜索注意事项在我们导入模块的时候有可能出现模块名字重名的情况大家可能会想我们约定好给模块起名字不重名不就可以了吗 但是一个项目中的模块不可能是一个码农写的总会有这种可能性还有我们模块名也有可能和内建模块重名也有 可能和第三方模块重名这些可能性都有所以我们要清楚当模块重名的情况下Python 会按照 sys.path 列表的顺序查找的当第一次查到后就不会再继续查找该模块。假定我们创建一个模块 abs 和内建模块重名我们本意是调用 Python 内置的 abs 函数做绝对值计算但是 Python 根据 sys.path 列表里面的值率先找到我们自己写的 abs 模块就停止了搜索。 hello.py 文件。 importabsprint(abs(9))# 这时候用的是我们自己模块 abs 而不是 Python 内置的 abs 函数所以报错。我们自定义的模块一般放在项目目录下这是一个好的习惯内置模块我们安装 Python 解释器的时候Python 把它放在安装目录下了第三方模块我们一般自动安装在 Python 安装目录下的 lib 目录下的 site-packages 目录下。3️⃣ 如何安装第三方模块在 Python 中我们安装第三方模块有三种方式。第一种方式是第三方模块提供一个安装程序 我们用 Python 解释器去执行这个程序即可剩下两种方式是通过 setuptools 这个工具完成的。Python 有两个封装了 setuptools 的包管理工具easy_install 和 pip目前官方推荐使用 pip这两个模块在 Python 3.7 版本 中已经作为内置模块存在了所以我们不需要安装即可使用这两个模块。本节课我们全面学习以上三种方法去安装第三方模块。Python 直接安装我们现在以安装第三方模块 six 为例来详细介绍如何使用 Python 解释器直接安装该模块。 首先我们需要网上下载我们需要安装的模块包 点击进入 six 模块所在官网下载源码压缩包到本地然后解压。在控制台里面进入解压后的 six 模块里 setup.py 所在的文件夹然后执行 Python setup.py install 即可。我们知道第三方模块一般安装在 Python 解释器所在安装目录下的 lib 目录下的 site-packages 目录下通过查看我们发现确实安装上了。第三方模块的使用方式和内建模块以及自定义模块使用方式一样我们在安装 six 时six 自带的 setup.py 程序自动把 six 模块所在路径添加到 sys.path 中了所以我们直接导入即可。有时候我们需要安装的第三方模块包并没有提供 setup.py 文件所以我们无法通过 Python 直接安装这个时候我们可以使用包管理工具 easy_install 或 pip 方式安装。使用 easy_install 安装我们知道在 Python 3.7 版本中Python 解释器已经把 easy_install 作为 Python 内置模块了我们可以直接使用该模块我们使用 easy_install 模块安装第三方模块不需要自己手动下载第三方模块我们可以在任意目录下直接使用 easy_install packageName 来安装第三方模块easy_install 会自动到模块管理库里面找我们要安装的第三方模块的地址自动下载到本地然后进行安装。easy_install 同样会把第三方模块安装到 Python 解释器所在安装目录下的 lib 目录下的 site-packages 目录下大家可以自行查看在此就不在赘述使用方法也一样。使用 pip 安装我们知道在 Python 3.7 版本中Python 解释器已经把 pip 作为 Python 内置模块了我们可以直接使用 pip 安装第三方模块。我们使用 pip 模块安装第三方模块不需要自己手动下载第三方模块我们可以在任意目录下直接使用 pip install packageName 来安装第三方模块pip 会自动到模块管理库里面找我们要安装的第三方模块的地址自动下载到本地然后进行安装。pip 同样会把第三方模块安装到 Python 解释器所在安装目录下的 lib 目录下的 site-packages 目录下。pip 关于安装路径问题和上面两种方法不同的是上面两中方法在安装模块的时候会在 site-packages 目录下创建一个以该模块名加版本号命名的文件夹包把所有该模块的类库函数放在在这个包下然后把这个文件夹的全路径加入到 sys.path 里面 而用 pip 安装时则是直接在 site-packages 目录下创建一个以该模块名命名的文件夹包把所有该模块的类库函数放在在这个包下然后再创建一个以该模块名加版本号命名的文件夹放入 该模块的说明信息因为 site-packages 所在全路径已经在 sys.path 里面所以我们可以直接使用该模块。第三方模块大都是外国友人写的模块所在的服务器也在国外由于祖国伟大的 Great Firewall 的存在我们在使用 pip 安装这些模块时可能导致下载失败无法安装这时候我们可以使用国内镜像来安装。 使用镜像的安装命令为pip install -i packageUrl packageName比如我们使用国内清华大学的镜像安装 six 模块可以执行命令pip install -i https://pypi.tuna.tsinghua.edu.cn/simple six。下面表格中我们列出国内主流的镜像地址。机构名称镜像地址示例比如用镜像安装 six阿里云https://mirrors.aliyun.com/pypi/simplepip install -i https://mirrors.aliyun.com/pypi/simple six豆瓣https://pypi.douban.compip install -i https://pypi.douban.com six清华大学https://pypi.tuna.tsinghua.edu.cn/simplepip install -i https://pypi.tuna.tsinghua.edu.cn/simple six中国科学技术大学https://pypi.mirrors.ustc.edu.cnpip install -i https://pypi.mirrors.ustc.edu.cn six华中科技大学https://pypi.hustunique.compip install -i https://pypi.hustunique.com six山东理工大学https://pypi.sdutlinux.orgpip install -i https://pypi.sdutlinux.org sixpip 还有其它功能比如查看更新卸载第三方模块等等下面我们列出常用的命令。功能命令示例下面对更新移除搜索操作以 six 模块为例查看使用pip已安装的模块pip listpip list更新第三方模块pip install -U packageNamepip install -U six移除第三方模块pip uninstall packageNamepip uninstall six搜索第三方模块pip search packageNamepip search six查看帮助文档pip helppip help升级pippip install -U pippip install -U pip当然我们也可以使用 pip 同时安装多个模块只需要每个模块用空格隔开即可比如我们想同时安装 six 模块, pillow 模块和 requests 模块操作命令如下。pipinstallsix pillow requests我们的 pip 维护的数据仓库也不是万全的有时候有的第三方模块没有地址加入到 pip 的数据仓库中但是一般模块本身都提供一个后缀名为 whl 的文件我们可以使用pip install whl文件名或easy_install whl文件名进行安装下面我们举例使用 pip 安装 whl 文件。pip 很强大它本身是包管理工具用 pip 安装第三方模块时pip 本身可以根据我们的 Python 版本自动找到适用的第三方模块版本。我们以后要经常使用 pip 来安装第三方模块几乎用不到前面两种安装方式。4️⃣ 虚拟环境Python 的虚拟环境可以使一个 Python 程序拥有独立的库和解释器而不用与其它 Python 程序共享用一个库。虚拟环境的好处是避免了不同 Python 程序间的互相影响如果我们不使用虚拟环境我们在开发项目A时可能需要某个库的 1.0 版本,而我们又需要开发项目 B而项目 B 需要同样这个库的 2.0 版本如果程序 B 执行则 A 就不能执行了。virtualenv 是可以创建和管理虚拟环境的第三方模块我们可以用该 virtualenv 创建虚拟且独立的 python 运行环境使得单个项目的运行环境与其它项目独立起来。安装和使用 virtualenv首先我们用 pip 来安装 virtualenv为了防止国外网速慢或下载失败我们使用使用国内镜像。pipinstall-ihttps://mirrors.aliyun.com/pypi/simple virtualenv# 使用阿里云镜像安装我们知道第三方模块一般被安装在 Python 解释器所在的根目录下的 Lib 目录下的 site-packages 目录下virtualenv 模块同样被安装在该目录下。同时 virtualenv 也提供一个 exe 程序方便我们直接使用我们以后直接使用该 exe 程序来创建虚拟环境这个 exe 文件放在 Python 解释器所在的根目录下的 Scripts 目录下。首先我们进入本地 Python 解释器所在的根目录下的 scripts 目录下 然后使用命令virtualenv.exe myenv来创建虚拟环境myenv 是新创建的虚拟环境的名称该虚拟环境是一个文件夹, 里面是了一个独立的 Python 执行环境。virtualenv.exe myenv # 创建虚拟环境该虚拟环境被创建在你控制台执行命令时所在的当前路径下 因为我们是进入本地 Python 解释器所在的根目录下的 scripts 目录下执行的创建命令所以虚拟环境 myenv 被创建在该目录C:\Python3\Scripts下。当然我们也可以把虚拟环境创建在其它任何目录下。 有时候为了打包方便我们会把虚拟环境创建在项目根目录下比如我们想把虚拟环境创建在E:\python_test项目路径下此时我们只需要在控制台下进入项目目录下调用 virtualenv 来创建虚拟环境即可注意要写上virtualenv.exe 所在的全路径。项目开发中使用虚拟环境下面为了方便学习我们就以上面创建在 C:\Python3\Scripts 路径下的虚拟环境为例。虚拟环境创建好之后我们就可以在我们的虚拟环境下安装我们的项目需要的第三方模块在安装第三方模块之前我们要先进入虚拟环境目录并激活虚拟环境。 激活虚拟环境的命令为activate当虚拟环境激活成功当前路径前面会多出一个虚拟环境的名称。激活虚拟环境后我们可以使用 pip 把第三方模块安装到虚拟环境下下面我们准备把 Pillow 模块安装到虚拟环境下。我们可以用 deactivate 命令退出我们激活的虚拟环境。当然我们开发项目使用的是 Pycharm比如我们让项目 python_test 使用虚拟环境 myenv只需要在 Pycharm 下给要开发的项目配置虚拟环境 myenv 下的 Python 解释器即可。把项目和虚拟环境关联好后直接运行我们发现项目调用的是虚拟环境下的解释器。如果我们想永久废弃虚拟环境 myenv直接删掉 myenv 文件夹就可以了。注意事项大家一定要熟悉 Python 解释器路径的查找规则查找规则为当前路径下 Python 解释器 虚拟环境所在路径下 Python解释器 环境变量路径下 Python 解释器。比如在控制台下激活虚拟环境后把当前路径切换到 E 盘然后进入 python 解释器环境使用代码print sys.executable打印出当前使用的 python 解释器路径。大家可以做一个试验把 python.exe 程序拷贝到 E 盘激活虚拟环境后把当前路径切换到 E 盘进入 python 解释器环境然后打印出当前 python 解释器使用的路径看看调用的是哪个 Python 解释器。最后说一句大家做项目开发中要养成一个好习惯对每一个项目都关联独立的虚拟环境。5️⃣ 推荐的项目环境操作可以使用python -m venv .venv创建项目环境激活后再运行python -m pip install 包名。这样做能减少系统 Python、多个项目和多个pip命令之间的混淆。项目所需依赖应记录在依赖文件或项目配置中不要依赖开发机器上碰巧已经安装的包。 文章小结模块和包让代码按职责组织导入能否成功取决于模块搜索路径与当前解释器环境避免把自定义模块放进解释器安装目录。使用python -m pip安装、查看和卸载依赖确认命令对应的解释器为不同项目分别创建虚拟环境避免依赖版本相互影响。可将类与函数放进同一个包供另一脚本导入再创建两个虚拟环境分别安装不同版本的 Pillow核对各环境的依赖列表。