人工智能之编程基础 Python 入门
第九章 模块与包
@
前言
本章节主要学习python模块与包,同样也会涉及到特殊变量__name__变量__main__变量、__all__变量和__init__.py文件
模块
在 Python 中,模块(Module) 是组织代码的基本单元。一个模块就是一个包含 Python 定义和语句的文件,其文件名就是模块名加上 .py 后缀。
1. 模块的基本概念
什么是模块?
- 一个
.py文件就是一个模块 - 模块可以包含函数、类、变量和可执行代码
- 模块有助于代码的组织、重用和命名空间管理
# math_utils.py (模块文件)
def add(a, b):
return a + b
def multiply(a, b):
return a * b
PI = 3.14159
2. 导入模块
1. import 语句
# 导入整个模块
import math_utils
result = math_utils.add(3, 4) # 使用模块中的函数
print(math_utils.PI) # 使用模块中的变量
2. from ... import ...
# 导入特定函数/变量
from math_utils import add, multiply, PI
result = add(3, 4) # 直接使用,无需模块前缀
area = PI * 5 ** 2
3. from ... import *
# 导入所有公共名称(不推荐)
from math_utils import *
result = add(3, 4) # 可以直接使用
注意:这种方式可能导致命名冲突,建议明确导入所需内容
4. import ... as ...
# 给模块起别名
import math_utils as mu
import numpy as np
import pandas as pd
result = mu.add(3, 4)
3. 模块搜索路径
Python 在导入模块时会按以下顺序搜索:
- 当前目录
- PYTHONPATH 环境变量指定的目录
- 标准库目录
- 第三方包安装目录(如 site-packages)
查看搜索路径:
import sys
print(sys.path)
添加自定义路径:
import sys
sys.path.append('/path/to/my/modules')
4. __name__ 和 __main__
每个模块都有一个内置变量 __name__:
# calculator.py
def main():
print("Calculator module")
result = add(5, 3)
print(f"5 + 3 = {result}")
if __name__ == "__main__":
main() # 只有直接运行此文件时才执行
else:
print(f"模块 {__name__} 被导入")
- 当模块被导入时:
__name__等于模块名(如'calculator') - 当模块被直接运行时:
__name__等于'__main__'
5. 标准库模块示例
Python 自带丰富的标准库模块:
# 数学运算
import math
print(math.sqrt(16)) # 4.0
# 随机数
import random
print(random.randint(1, 10))
# 日期时间
import datetime
now = datetime.datetime.now()
# 文件操作
import os
import shutil
# 正则表达式
import re
pattern = re.compile(r'\d+')
# 数据序列化
import json
data = json.loads('{"name": "Alice"}')
# 网络请求
import urllib.request
6. 第三方模块
使用 pip 安装第三方模块:
# 安装模块
pip install requests
pip install numpy
pip install pandas
# 查看已安装的模块
pip list
# 导出依赖
pip freeze > requirements.txt
使用第三方模块:
import requests
response = requests.get('https://api.github.com/users/octocat')
print(response.json())
7. 模块的属性和函数
查看模块内容
import math
# 查看模块的所有属性和方法
print(dir(math))
# 查看模块信息
print(help(math))
# 查看特定函数的帮助
help(math.sin)
动态导入
# 使用 __import__()
module_name = "math"
math_module = __import__(module_name)
# 使用 importlib (推荐)
import importlib
json_module = importlib.import_module("json")
8. 模块的最佳实践
1. 模块命名
- 使用小写字母
- 使用下划线分隔单词
- 避免与标准库模块同名
- 不要使用特殊字符
✅ 好的命名:data_processor.py, utils.py
❌ 不好的命名:DataProcessor.py, my-module.py
2. 模块结构
"""
模块文档字符串 - 描述模块的功能
"""
# 1. 导入标准库
import os
import sys
from datetime import datetime
# 2. 导入第三方库
import requests
# 3. 导入本地模块
from . import local_module
# 常量
DEFAULT_TIMEOUT = 30
MAX_RETRIES = 3
# 函数和类定义
def utility_function():
pass
class UtilityClass:
pass
# 主程序入口(可选)
if __name__ == "__main__":
pass
3. __all__ 变量
控制 from module import * 的行为:
# my_module.py
def public_function():
pass
def _private_function(): # 下划线开头表示私有
pass
class PublicClass:
pass
__all__ = ['public_function', 'PublicClass'] # 只允许导出这些
9. 常见问题和解决方案
1. 循环导入问题
# file1.py
from file2 import func_b
def func_a():
func_b()
# file2.py
from file1 import func_a # 循环导入!
def func_b():
func_a()
解决方案:
- 重构代码,消除循环依赖
- 在函数内部导入
- 使用字符串导入(延迟导入)
# 解决方案:在函数内部导入
def func_b():
from file1 import func_a
func_a()
2. 模块重新加载
import importlib
import my_module
# 修改了 my_module.py 后重新加载
importlib.reload(my_module)
3. 隐藏模块
创建隐藏模块(以 _ 开头):
# _internal.py
def secret_function():
pass
# 在 __init__.py 中不导出
__all__ = [] # 不包含 _internal
包
在 Python 中,包(Package) 是一种组织和管理多个相关模块的机制。它允许你将功能相关的模块组织在一起,形成一个层次化的结构,使大型项目更易于维护和管理。
1. 包的基本概念
什么是包?
- 包是一个包含多个模块的目录
- 包必须包含一个特殊的文件
__init__.py(Python 3.3+ 可选,但强烈建议保留) - 包可以包含子包,形成层次结构
包 vs 模块
| 模块 | 包 |
|---|---|
一个 .py 文件 |
一个包含模块的目录 |
math.py |
mypackage/ 目录 |
import math |
import mypackage |
2. 创建包
基本结构
mypackage/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
├── __init__.py
└── module3.py
__init__.py 文件的作用
# mypackage/__init__.py
"""
这是 mypackage 包的初始化文件
"""
# 1. 标识目录为 Python 包
# 2. 包的初始化代码
print("mypackage 正在加载...")
# 3. 控制导入行为
__all__ = ['module1', 'module2', 'subpackage']
# 4. 导入常用内容,方便用户使用
from .module1 import important_function
from .module2 import AnotherClass
# 5. 定义包级变量
__version__ = "1.0.0"
__author__ = "Your Name"
3. 包的导入方式
1. 导入整个包
import mypackage
# 使用包中的内容
mypackage.module1.some_function()
instance = mypackage.subpackage.module3.SomeClass()
2. 导入包中的特定模块
from mypackage import module1
from mypackage.subpackage import module3
result = module1.process_data()
obj = module3.create_object()
3. 导入包中的特定函数/类
from mypackage.module1 import process_data, DataProcessor
from mypackage.subpackage.module3 import create_object
# 直接使用
data = process_data("input.txt")
processor = DataProcessor()
4. 使用别名
import mypackage as mp
from mypackage import module1 as m1
result = mp.module2.analyze()
4. 相对导入 vs 绝对导入
绝对导入(推荐)
# 在 mypackage/subpackage/module3.py 中
from mypackage.module1 import helper_function
from mypackage.utils import config
相对导入(在包内部使用)
# 在 mypackage/subpackage/module3.py 中
from ..module1 import helper_function # 上一级目录
from ..utils import config # 上一级的 utils 模块
from . import local_module # 同级目录
相对导入规则:
.表示当前包..表示父包...表示祖父包
5. 实际项目结构示例
典型的项目结构
project/
├── main.py
├── requirements.txt
└── myapp/
├── __init__.py
├── config.py
├── models/
│ ├── __init__.py
│ ├── user.py
│ └── product.py
├── services/
│ ├── __init__.py
│ ├── user_service.py
│ └── order_service.py
├── utils/
│ ├── __init__.py
│ ├── database.py
│ └── helpers.py
└── api/
├── __init__.py
└── routes.py
使用示例
# main.py
from myapp.services.user_service import create_user
from myapp.models.user import User
from myapp import config
# 创建用户
user_data = {"name": "Alice", "email": "alice@example.com"}
user = create_user(user_data)
print(f"创建用户: {user.name}")
# myapp/services/user_service.py
from myapp.models.user import User
from myapp.utils.database import save_to_db
def create_user(user_data):
user = User(**user_data)
save_to_db(user)
return user
6. __init__.py 的高级用法
1. 精简导入接口
# mypackage/__init__.py
"""mypackage 主要接口"""
from .module1 import CoreProcessor
from .module2 import DataAnalyzer
from .utils.helpers import format_output
__all__ = ['CoreProcessor', 'DataAnalyzer', 'format_output']
# 现在用户可以这样使用:
# from mypackage import CoreProcessor, DataAnalyzer
2. 延迟导入(按需加载)
# mypackage/__init__.py
class LazyLoader:
def __init__(self, module_name, attribute_name=None):
self.module_name = module_name
self.attribute_name = attribute_name
self._module = None
def __getattr__(self, name):
if self._module is None:
self._module = __import__(self.module_name, fromlist=[''])
if self.attribute_name:
return getattr(self._module, self.attribute_name)
return getattr(self._module, name)
# 使用
heavy_module = LazyLoader('mypackage.heavy_operations')
3. 版本和元数据管理
# mypackage/__init__.py
__version__ = "2.1.0"
__author__ = "Your Name"
__email__ = "your.email@example.com"
__license__ = "MIT"
# 可以通过以下方式访问
# import mypackage
# print(mypackage.__version__)
7. 包的发布和安装
1. 创建 setup.py
# setup.py
from setuptools import setup, find_packages
setup(
name="mypackage",
version="1.0.0",
packages=find_packages(),
install_requires=[
"requests>=2.25.0",
"numpy>=1.19.0",
],
author="Your Name",
author_email="your.email@example.com",
description="A sample Python package",
python_requires=">=3.6",
)
2. 安装本地包
# 开发模式安装(修改代码立即生效)
pip install -e .
# 正常安装
pip install .
3. 发布到 PyPI
# 安装打包工具
pip install build twine
# 创建分发包
python -m build
# 上传到 PyPI
twine upload dist/*
8. 常见问题和解决方案
1. ModuleNotFoundError
ModuleNotFoundError: No module named 'mypackage'
解决方案:
# 方法1:添加到 sys.path
import sys
sys.path.append('/path/to/parent/directory')
# 方法2:使用 PYTHONPATH 环境变量
export PYTHONPATH="${PYTHONPATH}:/path/to/parent/directory"
# 方法3:正确安装包
pip install -e /path/to/package
2. 相对导入错误
# 错误:尝试在脚本中直接运行包含相对导入的文件
# ValueError: attempted relative import with no known parent package
解决方案:
# 正确的运行方式
python -m mypackage.module_name
# 而不是
python mypackage/module_name.py
3. 循环导入
# file1.py
from .file2 import func_b
# file2.py
from .file1 import func_a # 循环导入!
解决方案:
- 重构代码结构
- 在函数内部导入
- 使用字符串导入
# file2.py
def func_b():
from .file1 import func_a # 延迟导入
return func_a()
9. 最佳实践
1. 包设计原则
- 单一职责:每个包应该有明确的功能定位
- 高内聚:包内的模块应该紧密相关
- 低耦合:包之间依赖应该最小化
- 清晰的接口:通过
__init__.py提供清晰的公共 API
2. 命名规范
- 使用小写字母
- 使用下划线分隔单词
- 避免与标准库冲突
- 名称应该描述包的功能
✅ 好的包名:data_analysis, web_scraper
❌ 不好的包名:MyPackage, data-analysis
3. 文档和测试
# mypackage/__init__.py
"""
MyPackage - 数据处理工具包
提供一系列数据处理、分析和可视化的工具。
功能:
- 数据清洗
- 统计分析
- 报告生成
示例:
>>> from mypackage import DataProcessor
>>> processor = DataProcessor()
>>> result = processor.analyze(data)
"""
__version__ = "1.0.0"
4. 版本控制
- 使用语义化版本(Semantic Versioning)
MAJOR.MINOR.PATCH格式- 重大变更时更新 MAJOR 版本
总结
本文主要对模块以及包的详细学习和探讨,有助于后续学习更深一层的python各种算法库打下好的基础。一起努力成长!!
资料关注
相关资料获取:
公众号:咚咚王

《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen) 》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》
posted on
浙公网安备 33010602011771号