模块

模块入门

模块基本概念

概念

  • 模块(Module)= 一个 .py 文件
  • 内部可以包含函数、类、变量和可执行语句。
  • 模块的作用:
    • 代码重用:一份代码多处使用。
    • 结构化管理:把功能分块,逻辑清晰。
    • 封装性:对外只暴露接口,隐藏实现细节。

示例

mymodule.py 文件

# mymodule.py
def greet(name):
    print(f"你好,{name}!")

PI = 3.14159

main.py 文件

# main.py
import mymodule
mymodule.greet("Alice")
print(mymodule.PI)

易错点

  • 模块名就是文件名mymodule.pyimport mymodule
  • 不能用数字开头命名:❌ 123.py

最佳实践

  • 模块名尽量 简短、小写,避免与标准库同名。
  • 如果模块很大,考虑拆分为 包(Package)

导入模块

基本用法

import math
print(math.sqrt(16))  # 4.0

精确导入

from math import sqrt
print(sqrt(16))  # 4.0

使用别名

import math as m
print(m.pi)

一次导入多个

import os, sys

常见错误

from math import *  # 不推荐
  • 会引入所有名字,容易与当前作用域冲突。

最佳实践

  • 推荐 import 模块 as 别名,保持清晰。
  • 避免通配符导入(*)。

模块搜索路径

导入顺序

Python 在执行 import xxx 时,会按照以下顺序查找:

  1. 当前目录
  2. 环境变量 PYTHONPATH
  3. 系统默认路径(sys.path

查看搜索路径

import sys
print(sys.path)

修改搜索路径

import sys
sys.path.append("/my/custom/path")

易错点

  • 如果本地文件和标准库模块 同名,会导致冲突。比如 random.py 文件会覆盖内置 random 模块。

最佳实践

  • 避免与内置库同名。
  • 项目根目录推荐放一个 __init__.py,明确为包。

内置模块(标准库)

常见模块分类表

分类 模块 功能
系统接口 os 文件/目录操作
解释器接口 sys Python 运行环境
数学计算 math 基础数学
高级数学 cmath 复数
时间日期 datetime 时间处理
随机数 random 随机生成
正则 re 模式匹配
数据交换 json JSON 处理
序列化 pickle 保存 Python 对象
集合类 collections Counter, deque
函数式 functools 高阶函数工具
迭代器 itertools 无限序列
并发 threading/asyncio 线程 / 协程
网络 socket 套接字编程
数据库 sqlite3 轻量级数据库

示例

import random
print(random.choice(["苹果", "香蕉", "梨"]))

自定义模块

创建文件 mymath.py

def add(x, y):
    return x + y

使用模块

import mymath
print(mymath.add(2, 3))  # 5

相对路径导入

项目结构:

project/
    main.py
    utils/
        __init__.py
        tools.py

main.py 中:

from utils import tools

模块属性

__name__ —— 模块名

含义

  • __name__ 表示模块的名字。
  • 当你 直接运行一个 Python 文件 时,__name__ 的值会被设置为 "__main__"
  • 当这个文件作为 模块被导入 时,__name__ 的值就是模块的文件名(不包含 .py 后缀)。

使用场景

  • 最常见的用途是写在:
if __name__ == "__main__":
    # 只有直接运行文件时,下面的代码才会执行
    print("我被直接运行了")

这保证了模块既能当“脚本”运行,又能当“库”被导入。

示例

# 文件名 test_module.py
print(__name__)

if __name__ == "__main__":
    print("我是主程序")

执行 python test_module.py

__main__
我是主程序

在其他文件导入:

import test_module

输出:

test_module

__file__ —— 模块的文件路径

含义

  • __file__ 表示模块文件在磁盘上的 绝对路径或相对路径
  • 对于标准库中的某些模块(如 math),它可能是一个编译好的 共享库文件(.so/.pyd),而不是 .py 文件。
  • 对于内置模块(如 sys),可能没有 __file__ 属性,会报 AttributeError

使用场景

  • 确定模块的物理位置(调试、定位模块、动态加载资源时很常用)。

示例

import os
import math

print(os.__file__)   # 例如:/usr/lib/python3.11/os.py
print(math.__file__) # 例如:/usr/lib/python3.11/lib-dynload/math.cpython-311.so

注意:

import sys
print(sys.__file__)  # 报错,因为 sys 是内置模块

__doc__ —— 文档字符串

含义

  • __doc__ 是模块的 文档字符串,也就是文件开头写的多行注释(通常用 """ 三引号写)。
  • 如果没有写文档字符串,则值为 None

使用场景

  • 用来查看模块的用途说明,常和 help() 函数结合。
  • 写模块时推荐写好 __doc__,方便别人阅读。

示例

"""
这是一个示例模块,用来演示 __doc__ 属性。
"""

def add(a, b):
    """返回两个数的和"""
    return a + b

print(__doc__)

运行结果:

这是一个示例模块,用来演示 __doc__ 属性。

再试:

import math
print(math.__doc__)  # math 模块的文档

__dict__ —— 模块的命名空间(字典)

含义

  • __dict__ 存储模块中的 所有定义的变量、函数、类,以字典的形式返回。
  • 你可以用它来查看模块内部的所有成员。

使用场景

  • 调试时检查模块里有什么东西。
  • 也可以动态修改模块的内容(高级用法)。

示例

import math
print(math.__dict__.keys())   # math 模块里所有的函数、常量、类

输出(部分):

dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__',
'pi', 'e', 'sin', 'cos', 'tan', 'log', 'sqrt', ...])

会发现这些键和值正是 dir(math) 展示的内容,只是 __dict__ 是字典,dir() 返回的是列表。

模块高级用法

查看模块内容

import math
print(dir(math))  # 查看 math 模块里的所有函数

输出(部分):

['acos', 'asin', 'atan', 'ceil', 'cos', ...]

重新加载模块

import mymodule
import importlib

importlib.reload(mymodule)

注意:Python 会缓存模块,调试时常用 reload。

包(Packages)

  1. 包的结构

    mypkg/
        __init__.py
        sub1.py
        sub2.py
    
  2. 导入方式

    import mypkg.sub1
    from mypkg import sub2
    
  3. __init__.py

    • 表示目录是一个包。

    • 可以控制 from mypkg import * 导入哪些模块。

虚拟环境(venv)

  1. 创建环境

    python -m venv venv
    
  2. 激活环境

    • Windows: venv\Scripts\activate

    • Mac/Linux: source venv/bin/activate

  3. 安装依赖

    pip install requests
    
  4. 导出依赖

    pip freeze > requirements.txt
    

动态导入模块

module_name = "math"
m = __import__(module_name)
print(m.sqrt(9))

插件化开发

import importlib

plugins = ["math", "random"]
for name in plugins:
    mod = importlib.import_module(name)
    print(f"已加载 {name}")

懒加载

有时模块很大,可以在用到时再导入:

def heavy_task():
    import numpy
    print(numpy.arange(5))

打包模块(发布到 PyPI)

  • setuptoolspoetry

  • 目录结构:

    mylib/
        __init__.py
        core.py
    setup.py
    
  • 安装:

    pip install .
    

更多推荐