Python从入门到实战(十三):模块、包与环境管理

目录

一、为什么需要模块

[1. 什么是模块](#1. 什么是模块)

[2. 为什么要使用模块](#2. 为什么要使用模块)

[3. 模块的分类](#3. 模块的分类)

[4. 创建自己的模块](#4. 创建自己的模块)

二、模块导入

[1. import 导入](#1. import 导入)

[2. import ... as](#2. import ... as)

[3. from ... import](#3. from ... import)

[4. from ... import *](#4. from ... import *)

三、模块中的特殊变量

[1. name](#1. name)

[2. name 使用场景](#2. name 使用场景)

[3. all](#3. all)

[四、Python 标准库](#四、Python 标准库)

[1. 常见标准库简介](#1. 常见标准库简介)

[2. 常用标准库示例](#2. 常用标准库示例)

五、包(Package)

[1. 包与模块的区别](#1. 包与模块的区别)

[2. 标准的包目录结构](#2. 标准的包目录结构)

[3. init.py](#3. init.py)

[4. 创建包并导入](#4. 创建包并导入)

[5. 包的导入方式](#5. 包的导入方式)

六、第三方包

[1. PyPI 与 pip](#1. PyPI 与 pip)

[2. pip 常用命令](#2. pip 常用命令)

[3. list / show / freeze](#3. list / show / freeze)

[七、Python 运行环境](#七、Python 运行环境)

[1. 全局环境与虚拟环境](#1. 全局环境与虚拟环境)

[2. 为什么需要虚拟环境](#2. 为什么需要虚拟环境)

[3. 使用 venv 创建虚拟环境](#3. 使用 venv 创建虚拟环境)

[4. 激活与退出虚拟环境](#4. 激活与退出虚拟环境)

总结


一、为什么需要模块

随着业务逻辑的复杂度不断上升,项目的代码量走向成千上万行,或者需要引入第三方工具链时,如何高效地组织代码结构、防止命名冲突,以及如何精细化地管理运行环境,就成了衡量一个开发者工程素养的分水岭

本篇博客将系统地拆解 Python 的模块体系、包管理 以及现代虚拟环境的配置技巧


1. 什么是模块

在 Python 的底层物理世界中,模块的本质非常简单:它就是一个以 .py 结尾的 Python 代码文件

在这个 .py 文件里,你可以像平时一样声明变量、编写函数、定义类,甚至可以直接写执行语句。每一个模块在解释器眼中都是一个独立的命名空间


2. 为什么要使用模块

通过将大文件拆分成独立的模块,我们的程序可以获得以下便利:

  • 代码复用性:一个模块编写完成后,不仅可以在当前项目的不同地方被调用,还可以轻松地被其他项目导入,告别低效的复制粘贴

  • 命名空间隔离:不同的模块拥有各自独立的命名空间。这意味着,模块 A 里可以有一个叫 calculate() 的函数,模块 B 里也可以有一个叫 calculate() 的函数,它们在内存中互不干扰,完美解决了变量名冲突的痛点

  • 高可维护性:模块化的代码结构清晰、边界分明。哪里报错就去改对应的文件,改动只限制在局部模块内部,不会波及整体系统


3. 模块的分类

在 Python 中根据来源的不同,模块主要分为以下三类:

模块类型 本质与定义 代表
内置模块 随 Python 安装包自带的官方标准库,无需额外安装,由 C 语言或 Python 优化后常驻系统,可直接使用 sys, os, math, time
第三方模块 由开发者社区贡献并发布的开源库,需要通过 pip 工具下载并安装到本地环境中后方可使用 requests, numpy, pandas
自定义模块 开发者自己为了满足特定业务需求,在当前项目中创建的 .py 代码文件 my_tool.py, auth_service.py

4. 创建自己的模块

既然模块就是 .py 文件,那么创建它就非常简单。我们来做一个最直观的演练

第一步:创建一个独立的模块文件

在你的项目文件夹下,新建一个名为 calc.py 的文件,并在里面写下两个简单的数学工具函数。此时,calc.py 就已经是一个合法的自定义模块了:

python 复制代码
# 文件名: calc.py
"""
这是一个自定义的数学计算基础模块
"""

# 模块内部的变量
VERSION = "1.0.0"

# 模块内部的函数
def add(a: int, b: int) -> int:
    return a + b

def sub(a: int, b: int) -> int:
    return a - b

第二步:在其他文件中使用

现在,在这个项目文件夹下创建另一个文件,比如 main.py。如果我们想使用 calc.py 里的功能,只需要利用 import 关键字把这个模块引入进来即可:

python 复制代码
# 文件名: main.py

# 引入我们刚刚创建的自定义模块(注意:不需要写 .py 后缀)
import calc

# 通过 "模块名.属性名" 的方式安全调用
print(f"当前使用的计算模块版本是: {calc.VERSION}")

res1 = calc.add(10, 5)
res2 = calc.sub(10, 5)

print(f"加法结果: {res1}")
print(f"减法结果: {res2}")

这种设计使得 main.py 无需了解加减法的底层实现细节,只需要向 calc 模块发送指令即可。这正是代码拆分与模块化的魅力所在

二、模块导入

将代码拆分到不同的模块文件后,我们需要通过 "导入" 机制将它们组合并协同工作。Python 提供了多种导入语法,表面上它们只是写法不同,但在底层对命名空间的影响却截然不同


1. import 导入

最标准的导入方式是直接使用 import 关键字后跟模块名

  • 机制 :当执行 import calc 时,Python 解释器会完整执行一次 calc.py 文件,并在当前的内存中创建一个独立的 calc 命名空间

  • 调用:使用时必须携带模块名作为前缀(如 模块名.函数名)

python 复制代码
import calc

# 必须通过模块名点号(.)访问,清晰明确
print(calc.add(5, 3))

优点:非常安全。因为有 calc. 前缀保护,即使当前文件里也有一个叫 add 的函数,两者也绝不会搞混


2. import ... as

如果模块的名字太长,或者为了防止与当前文件中的变量重名,我们可以使用 as 关键字为导入的模块起一个别名

  • 机制:与基础导入完全一致,只是在当前文件的命名空间里,将原模块名替换为你指定的别名
python 复制代码
# 将 calc 模块重命名为 c
import calc as c

# 缩短了调用代码
print(c.add(5, 3))

3. from ... import

如果你只需要某个模块中的某一个或几个功能,而不想要整个模块,可以使用 from 语法进行精准提取

  • 机制 :把指定的函数或变量直接复制到当前的命名空间

  • 调用 :使用时直接写函数名即可,不再需要加模块名前缀

python 复制代码
# 只把 calc 模块里的 add 函数导入
from calc import add

# 调用时极其直接,不需要写 calc.add
print(add(5, 3))

注意 :这种方式虽然方便,但存在隐患。如果你在当前文件里又写了一个 def add():,那么从模块里导入的 add 就会被你后面写的同名函数静默覆盖


4. from ... import *

该写法会将目标模块中所有允许公开的变量和函数全部导入当前命名空间

python 复制代码
# 警告:这是一种不推荐的写法
from calc import *

print(add(5, 3))
print(sub(5, 3))

为什么不推荐使用 import *

  • 命名空间污染:如果 calc 模块里有 100 个函数,import * 会把这 100 个名字全部导入到当前的文件。你可能根本不知道自己不知不觉中引入了哪些名字

  • 代码可读性下降:后续维护代码的人看到一行 result = run_task(),他在当前文件里找不到 run_task 的定义,只能挨个去排查那些用了 import * 的模块,极度低效

  • 静默覆盖:如果两个不同的模块里都包含一个叫 parse() 的函数,你连续写了 from a import * 和 from b import *,那么模块 B 的 parse 会直接把模块 A 的 parse 覆盖掉,而且程序不会报任何错误,排查难度极大

三、模块中的特殊变量

当 Python 解释器加载一个 .py 模块文件时,它会自动在后台为这个模块创建一批内置特殊变量。其中,nameall 是日常工程开发中使用频率最高的两个变量


1. name

name 是一个内置的字符串变量,它的值是由 Python 解释器动态赋值的。它的核心作用是:告诉当前的模块,它是被别人导入使用的,还是被直接运行的

它的赋值规则非常简单:

  • 规则 A :如果这个 .py 文件是被用户作为主程序直接启动的(例如在终端输入 python main.py),Python 解释器就会把 name 赋值为 "main"

  • 规则 B :如果这个 .py 文件是被其他文件导入 的,Python 解释器就会把 name 赋值为这个模块本身的名字(字符串形式)


2. name 使用场景

为什么几乎每个 Python 项目都有 if name == "main"

让我们先看看一个常见的翻车案例

假设我们写了一个工具模块 tools.py,里面提供了一个求平方的函数。为了测试这个函数,我们在文件最下方写了一行测试执行代码:

python 复制代码
# 文件名: tools.py

def square(x: int) -> int:
    return x * x

# 直接在文件底部写死测试代码
print(f"--- 正在 tools 模块内部进行功能测试 ---")
print(f"测试结果: {square(4)}")

现在,我们在另一个核心业务文件 app.py 中想要导入并使用这个 square 函数:

python 复制代码
# 文件名: app.py
from tools import square

print("--- 业务启动 ---")
print(f"业务计算结果: {square(10)}")

运行 app.py 的结果

问题在哪?

app.py 导入 tools 模块时,Python 会把 tools.py 从头到尾执行一遍。结果,tools.py 底部原本用来做临时测试的代码也被执行了!这在生产环境中会导致严重的逻辑混乱(例如测试代码里包含了删库或发邮件的操作)

使用 if name == "main" 进行隔离

我们利用 name 的动态赋值特性,把 tools.py 改写为如下形式:

python 复制代码
# 文件名: tools.py

def square(x: int) -> int:
    return x * x

# 只有当直接运行 tools.py 时,下面这段代码才会被运行
if __name__ == "__main__":
    print(f"--- 正在 tools 模块内部进行功能测试 ---")
    print(f"测试结果: {square(4)}")

再次运行的效果:

  1. 如果你直接运行 tools.py :此时 name 的值是 "main",条件成立,测试代码正常打印

  2. 如果你运行 app.py :此时 tools.py 是被导入的,它的 name 变成了 "tools",条件不成立,底部的测试代码被完美静默屏蔽

if name == "main" 充当了模块的本地测试应用程序的唯一启动入口。它成功实现了 "函数定义" 与 "脚本执行" 的分离


3. all

除了 name,另一个常见的特殊变量是 all。它是一个由字符串组成的列表,专门用来约束 from module import * 这种通配符导入行为

如果在模块中定义了 all,那么当外部企图用 import * 导入所有内容时,只有被写在 all 列表里的名字才会被允许导出,没写在里面的变量或函数则会被隐藏

python 复制代码
# 文件名: api.py

# 显式声明:当外部使用 import * 时,只暴露 get_data 函数
__all__ = ["get_data"]

def get_data() -> str:
    return "公共数据"

def _secure_connect() -> None:
    print("底层连接(不希望被外部滥用)")

def debug_tool() -> None:
    print("内部调试工具(不暴露给用户)")

all 为模块提供了一层面向对象的 "封装保护"。它明确指定了哪些是供外部调用的公共接口 ,哪些是属于模块内部的私有实现,避免了外部对模块内部细节的过度依赖

四、Python 标准库

Python 官方在安装包中已经内置了大量功能强大的模块,统称为标准库

日常开发中,绝大多数基础任务(如文件读写、系统交互、时间计算)都可以直接使用标准库解决,完全不需要自己从零造轮子


1. 常见标准库简介

为了保持学习的轻量化,我们快速熟悉日常开发中最常用的 6 个核心标准库:

  • sys (System)

    • 功能:专门负责与 Python 解释器本身进行交互

    • 常见用途:获取终端传入的命令行参数(sys.argv)、查看当前 Python 的查找路径(sys.path)或强行退出程序(sys.exit())

  • os (Operating System)

    • 功能:负责与运行代码的操作系统环境进行沟通

    • 常见用途:获取当前工作目录(os.getcwd())、创建或删除文件夹、读取操作系统的环境变量

  • pathlib

    • 功能:Python 3 引入的用来替代传统 os.path 的现代路径操作库

    • 常见用途:用面向对象的方式拼接路径、判断文件是否存在、遍历文件夹,语法比 os 更直观

  • datetime

    • 功能:专门用来处理年、月、日、时、分、秒的时间节点与时间差计算

    • 常见用途:获取当前系统时间、将时间格式化为可读的字符串、计算具体日期

  • random

    • 功能:负责生成伪随机数,进行概率抽样

    • 常见用途:生成随机整数(randint)、在列表里随机抽取(choice)、把一个干净的列表随机打乱(shuffle)

  • math

    • 功能:提供了标准的数学常数和各种高级算术函数

    • 常见用途:向上取整(ceil)、向下取整(floor)、计算平方根(sqrt)以及使用圆周率 math.pi


2. 常用标准库示例

下面用一段简短的代码,展示其中几个标准库在实际项目中的常见用法:

python 复制代码
import datetime
import pathlib
import random
import sys

# 1. 使用 sys 检查当前的 Python 版本信息
print(f"当前系统运行的 Python 版本: {sys.version.split()[0]}")

# 2. 使用 datetime 获取当前时间,并格式化输出
now = datetime.datetime.now()
# 格式化输出当前时间
print(f"当前时间: {now.strftime('%Y-%m-%d %H:%M:%S')}")

# 3. 使用 pathlib 判断文件是否存在
# 创建一个路径对象指向当前目录下的 'config.ini'
file_path = pathlib.Path("config.ini")
print(f"config.ini 文件是否存在? -> {file_path.exists()}")

# 4. 使用 random 模拟一个简单的随机抽奖
users = ["张三", "李四", "王五", "赵六"]
lucky = random.choice(users)
print(f"本次随机抽取的是: {lucky}")

五、包(Package)

当项目继续扩大,我们的自定义模块文件可能会从几个激增到几十个。如果把这些 .py 文件随意丢在项目的根目录下,整个目录会变得极其混乱

为了解决模块文件的堆积问题,Python 引入了包的概念。简单来说,包就是通过文件夹来组织和管理多个模块的方式


1. 包与模块的区别

我们可以用一个非常直观的物理比喻来区分它们:

  • 模块 :是一张独立的CD光盘(一个 .py 文件),里面录制了几首具体的歌曲(函数、类)

  • :是一个收纳盒(一个文件夹),里面整整齐齐地摆放着多张CD光盘(多个模块文件)


2. 标准的包目录结构

我们用直观的树状图展示一个标准 Python 项目的包结构。这种目录划分在实际工程中非常常见:

python 复制代码
project/
│
├── main.py                # 整个项目的启动总入口
│
├── utils/                 # 工具类公共包(文件夹)
│   ├── __init__.py        # 包的标识与初始化文件
│   ├── math_tools.py      # 工具模块A:数学计算
│   └── string_tools.py    # 工具模块B:字符串处理
│
└── models/                # 数据模型包(文件夹)
    ├── __init__.py        # 包的标识与初始化文件
    └── student.py         # 模型模块:学生数据结构

3. init.py

在上面的结构图中,每个包的文件夹下都有一个__init__.py 文件

  • 标识 :只要一个文件夹下包含了 init.py 文件,Python 解释器就会把这个文件夹当成一个正式的 Python 包,而不是一个普通的普通文件夹

  • 自动初始化 :当你第一次导入这个包时,Python 会在后台自动物理执行一次该包下的 init.py 文件。你可以在里面写一些包的全局初始化配置,或者留空(完全空白的文件也是合法的)


4. 创建包并导入

我们按照上面的设计图,编写最简化的代码来实现包的联动

步骤一:编写包内部的子模块

在 utils/math_tools.py 写入一个数字翻倍函数:

python 复制代码
# 文件路径: utils/math_tools.py

def double_num(x: int) -> int:
    """把输入的数字乘以 2"""
    return x * 2

在 models/student.py 写入一个获取学生信息的函数:

python 复制代码
# 文件路径: models/student.py

def get_info(name: str) -> dict[str, str]:
    """生成学生基础信息字典"""
    return {"status": "active", "name": name}

此时在 utils/ 和 models/ 文件夹下各新建一个完全空白的 init.py 文件

步骤二:在根目录的 main.py 中导入使用

在最外层的 main.py 中,我们可以利用点号(.)作为路径分隔符,安全地将不同文件夹下的模块功能导入进来:

python 复制代码
# 文件路径: main.py

# 导入方式 A:从 utils 包的 math_tools 模块中导入函数
from utils.math_tools import double_num

# 导入方式 B:直接导入 models 包下的整个 student 模块
from models import student


# 1. 调用工具包的功能
res_val = double_num(5)
print(f"utils 包计算结果: {res_val}")

# 2. 调用模型包的功能(因为导入的是整个模块,调用时需要带模块名)
stu_data = student.get_info("小明")
print(f"models 包返回数据: {stu_data}")

5. 包的导入方式

在处理包时,我们的核心目标是透过文件夹,拿到里面的模块或函数。以下是几种导入方法:

点号 (.) 导入

点号在包中充当 "路径分隔符",类似于电脑文件夹中的斜杠(/ 或 \)

  • 方式 A(导入整个子模块)

    python 复制代码
    import utils.math_tools
    
    # 调用时:必须写完整前缀
    res = utils.math_tools.double_num(5)

    这种方式虽然安全,但调用起来极其累赘,一般不推荐

  • 方式 B(从子模块中导入函数)

    python 复制代码
    from utils.math_tools import double_num
    
    # 直接调用即可
    res = double_num(5)

as 关键字

当你使用 import utils.math_tools 觉得前缀太长,但又想保留模块命名空间时,用 as 起一个简短的别名是完美的方案

python 复制代码
# 把"包名.模块名"缩写为 mt
import utils.math_tools as mt

# 调用时:用别名代替超长路径
res = mt.double_num(5)

通配符导入

很多开发者会理所当然地认为,写一行 from utils import * 就能把 utils 文件夹下所有的 .py 模块全部一次性导入进来

但是默认情况下,这样导入会直接失效(什么都没导入进来)!

  • 背后原因:由于操作系统的文件系统差异,Python 无法安全、高效地自动去遍历并加载一个文件夹下的所有文件

  • 解决方案:利用 init.py 中的 all: 如果想让 from utils import * 起作用,你必须在 utils/init.py (包的初始化文件)中,手动写下白名单:

    python 复制代码
    # 文件路径: utils/__init__.py
    
    # 明确告诉 Python,当外部对这个包使用 import * 时,允许加载哪些子模块
    __all__ = ["math_tools", "string_tools"]

    有了这一步声明后,外部的代码才能顺利地使用通配符:

    python 复制代码
    # 此时可以成功导入 utils 目录下 __all__ 声明的所有子模块
    from utils import *
    
    # 可以直接使用 math_tools 模块了
    res = math_tools.double_num(5)

六、第三方包

Python 之所以能在数据科学、人工智能和Web开发等领域独占鳌头,除了得益于其优雅的语法外,更因其拥有庞大的全球第三方开源生态

在开发实践中,仅需执行一条简单指令,即可将这些功能强大的第三方包集成至本地环境


1. PyPI 与 pip

PyPI (Python Package Index) 是 Python 官方维护的、全球最大的第三方软件包仓库

你可以把它理解为手机里的 "应用商店"。任何开发者都可以把自己写的 Python 包上传到 PyPI 上供全世界免费下载

pip 简介

有了应用商店,我们自然需要一个 "安装包下载器"。在 Python 中,这个工具就是 pip(Python 默认自带的包管理命令行工具)

pip 会自动联网访问 PyPI 服务器,找到你想要的包,下载其文件,并自动解决它与其他包之间的依赖关系,安全地安装到你的 Python 环境中


2. pip 常用命令

在日常开发和线上部署中,我们每天都在跟以下这些高频命令打交道:

类型 命令行指令 效果
基础安装 pip install numpy 从 PyPI 自动下载并安装 NumPy 库
更新包 pip install --upgrade numpy 将已安装的 NumPy 升级到最新版本
卸载包 pip uninstall numpy 彻底从本地环境中移除 NumPy 库
查看列表 pip list 列出当前环境里所有已安装的第三方包及版本
查看详情 pip show numpy 展示 NumPy 包的安装路径、作者、依赖等详细信息
导出依赖 pip freeze > requirements.txt 将当前环境所有安装包及精确版本号重定向导出为一个配置文件
批量安装 pip install -r requirements.txt 依据配置文件,一键批量还原、安装项目所需的所有依赖包

3. list / show / freeze

这三个命令是软件工程团队协作和线上部署的核心基石,我们逐一拆解:

pip list:

在排查某些第三方库冲突时,我们第一步往往是输入 pip list。它会在控制台打印出一个列表,告诉你当前环境里到底存在哪些包:

pip show <包名>

有时候我们安装了某个包,但程序报错说 "找不到对应的模块",或者你想知道这个包具体被安装到了电脑的哪个文件夹下。此时 pip show 是最好的工具:

pip freeze

当你在自己的电脑上写好了一个网页程序,用了 requests 和 numpy,现在你要把代码发给同事运行。同事怎么知道他该装哪些包、装哪个版本? 你不需要写一个文件手动记录。你只需要在终端运行

python 复制代码
pip freeze > requirements.txt

这行指令会在你的项目根目录下生成一个名为 requirements.txt 的文本文件,内容干净规范:

同事拿到你的代码和这个文件后,在他的电脑终端只需执行一行:

复制代码
pip install -r requirements.txt

他的电脑就会按照你文件里的版本号,批量下载并还原出相同的运行环境

七、Python 运行环境

当我们开始使用 pip 安装各式各样的第三方库时,我们很快就会遇到每个 Python 开发者都必须面对的一大挑战------环境冲突

为了解决这一痛点,现代 Python 工程开发强制要求使用虚拟环境


1. 全局环境与虚拟环境

在探讨如何配置之前,我们首先从存储的角度看清两者的区别:

全局环境

  • 本质:当你第一次在电脑上安装 Python 时,系统里就会生成一个唯一的全局 Python 目录。所有的第三方包默认都会被塞进这个目录下的同一个 site-packages 文件夹里

  • 痛点 :如果你有项目 A(需要旧版 pandas 1.0)和项目 B(需要新版 pandas 2.0)。因为全局环境里同一个包只能存在一个版本,你安装 B 的版本就会覆盖 A 的版本,导致项目 A 直接崩溃

虚拟环境

  • 本质 :虚拟环境是一个完全独立的文件夹。在这个文件夹里,拷贝或链接了 Python 解释器的副本,并拥有它自己专属的、与其他环境绝对隔离的 site-packages 文件夹

  • 优势:当你在项目 A 的虚拟环境里装任何东西,都绝对不会影响项目 B,更不会污染你系统的全局环境


2. 为什么需要虚拟环境

除了解决版本冲突外,在真实的云服务器和多人协作中,虚拟环境还有以下不可替代的价值:

  • 避免破坏系统自带的 Python:许多操作系统底层的系统级工具高度依赖其系统自带的 Python。如果你直接在全局乱装、乱删第三方包,极易导致操作系统本身的某些核心功能瘫痪

  • 无需管理员权限:在服务器部署时,修改全局环境通常需要系统最高管理员权限(sudo)。而创建虚拟环境只需要在你拥有读写权的普通用户目录下建立文件夹即可

  • 轻量:一个虚拟环境实际上只占几十到上百 MB 的磁盘空间,项目不用了随时可以直接把这个文件夹删除


3. 使用 venv 创建虚拟环境

虽然许多 IDE 提供了图形化的环境配置,但在实际的生产环境部署、VSCode 插件开发或 Linux 服务器终端中,我们必须掌握最底层的命令行创建方式

自 Python 3.3 起,官方已经内置了名为 venv的轻量级虚拟环境创建工具,无需额外安装即可直接使用

步骤 A:打开终端并切换到项目根目录

创建 project 文件夹并使用 cd 命令进入

步骤 B:执行创建命令

在终端运行以下指令(命令中的 .venv 是你为你创建的虚拟环境文件夹起的名字,你可以自定义,但工业界一般默认使用 .venv):

bash 复制代码
# Windows / macOS / Linux 统一指令(有些 Linux 系统可能需要用 python3)
python -m venv .venv

此时,你会发现你的项目目录下多出了一个名为 .venv 的文件夹。打开它会发现里面有 Include、Lib、Scripts(或 bin)等文件夹。它现在已经是一个五脏俱全的微型 Python 世界了


4. 激活与退出虚拟环境

创建好虚拟环境后,它只是静静地躺在硬盘里。如果你直接运行 python 或 pip install,调用的依然是系统的全局环境。我们必须显式地激活它

激活虚拟环境

不同操作系统由于终端外壳不同,激活命令也有所区别。请根据你的系统在终端执行对应命令:

  • Windows 命令行 (CMD):

    bash 复制代码
    .venv\Scripts\activate.bat
  • Windows PowerShell:

    bash 复制代码
    .venv\Scripts\Activate.ps1
  • macOS / Linux:

    bash 复制代码
    source .venv/bin/activate

一旦激活成功,命令行提示符最前面会出现一个括号,里面写着你虚拟环境的名字,形如:

只要看到这个 (.venv) 前缀,说明此时你运行的 python 已经是这个独立虚拟环境的解释器,运行 pip install 也会安全地把包装进 .venv 内部,与外界彻底隔离

退出虚拟环境

当你完成了当前项目的开发,想要回到全局环境,或者切换到别的项目时,退出虚拟环境极其简单。在终端的任何路径下,直接敲入一行指令即可:

bash 复制代码
deactivate

敲击回车后,命令行前缀的 (.venv) 会瞬间消失,说明已经回到了系统全局环境

虚拟环境文件夹(如 .venv)内部包含了大量的系统软链接和具体的物理路径文件,它是绝对不可移植的 (即:你不能把 .venv 复制给别人用)

因此,在进行 Git 版本控制时,必须将**.venv 文件夹写入 .gitignore 文件中**,绝对不要把它上传到 GitHub。正如我们在上一章所学,我们应该上传 requirements.txt 配置文件,由别人拉取代码后自己在本地用 python -m venv .venv 重新生成全新的干净环境

总结

本章介绍了 Python 中模块与包的基本概念,学习了模块的创建与导入、包的组织方式、init.py 文件的作用以及第三方包的安装与管理。同时,我们还了解了 PyPI、pip 以及全局环境和虚拟环境之间的关系,掌握了 Python 项目中代码组织和开发环境管理的基本方法。合理地使用模块、包和虚拟环境,不仅能够提高代码的复用性,也能够使项目结构更加清晰、规范

下一篇文章我们将学习 Python 迭代器与生成器,深入理解 Python 中数据遍历的底层机制,并学习如何利用生成器实现更加高效、节省内存的数据处理方式

相关推荐
就叫飞六吧8 小时前
子页面和dialog案例
开发语言·javascript·ecmascript
李宸净9 小时前
Web自动化测试selenium+python
前端·python·selenium
而后笑面对9 小时前
生信bwa算法
python
倒流时光三十年9 小时前
Logback 系列(3):三大核心组件 Logger / Appender / Encoder
java·开发语言·logback
Darkwanderor10 小时前
动、静态库相关内容的详细介绍
linux·c语言·开发语言·c++
文祐10 小时前
C++类之虚函数表没有虚继承的菱形继承
开发语言·c++·算法
sycmancia10 小时前
Qt——另一种创建线程的方式
开发语言·qt
至乐活着10 小时前
深入Python内存管理与垃圾回收:从引用计数到分代回收的实战解析
python·性能优化·内存管理·垃圾回收·引用计数
m0_5474866611 小时前
《Python数据分析与挖掘》全套PPT课件
python·数据挖掘·数据分析