Python基础编程:模块和包、pip命令、自定义模块和包、包的初始化、常用包

学习目标

  • 理解模块和包的概念
  • 掌握模块的导入和使用方法
  • 学会创建自定义模块和包
  • 掌握pip包管理工具的高级用法
  • 了解常用的Python标准库和第三方库
  • 学会组织和管理项目结构

1. 模块基础

1.1 什么是模块

模块是一个包含Python代码的文件,可以定义函数、类和变量,也可以包含可执行的代码。模块让你能够有逻辑地组织Python代码段。

1.2 模块的优点

  • 代码复用:可以在多个程序中使用相同的模块
  • 命名空间管理:避免命名冲突
  • 代码组织:将相关代码组织在一起
  • 可维护性:模块化设计便于维护和更新

1.3 创建模块

创建一个名为math_utils.py的文件:

# math_utils.py

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

def subtract(a, b):
    """返回两个数的差"""
    return a - b

def multiply(a, b):
    """返回两个数的积"""
    return a * b

def divide(a, b):
    """返回两个数的商"""
    if b == 0:
        raise ValueError("除数不能为0")
    return a / b

# 模块级别的变量
PI = 3.14159
E = 2.71828

# 测试代码
if __name__ == "__main__":
    print("测试math_utils模块")
    print(f"3 + 4 = {add(3, 4)}")
    print(f"10 - 3 = {subtract(10, 3)}")
    print(f"5 * 6 = {multiply(5, 6)}")
    print(f"15 / 3 = {divide(15, 3)}")

2. 模块的导入

2.1 import语句

# 导入整个模块
import math_utils

# 使用模块中的函数
result = math_utils.add(5, 3)
print(result)  # 输出:8

# 使用模块中的变量
print(math_utils.PI)  # 输出:3.14159

2.2 from…import语句

# 从模块中导入特定的函数
from math_utils import add, subtract

# 直接使用函数,不需要模块名前缀
print(add(10, 5))      # 输出:15
print(subtract(10, 5)) # 输出:5

# 导入所有内容(不推荐)
from math_utils import *
print(multiply(3, 4))  # 输出:12

2.3 导入时重命名

# 给模块起别名
import math_utils as mu
print(mu.divide(20, 4))  # 输出:5.0

# 给函数起别名
from math_utils import add as addition
print(addition(7, 8))  # 输出:15

2.4 导入多个模块

# 在一行中导入多个模块
import os, sys, datetime

# 更好的做法是分行导入
import os
import sys
import datetime

# 从同一模块导入多个内容
from math import sin, cos, tan, pi

3. Python标准库模块

3.1 os模块

import os

# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前目录:{current_dir}")

# 列出目录内容
files = os.listdir('.')
print(f"文件列表:{files}")

# 创建目录
os.makedirs('new_folder/subfolder', exist_ok=True)

# 路径操作
path = os.path.join('folder', 'subfolder', 'file.txt')
print(f"路径:{path}")

# 检查路径是否存在
exists = os.path.exists('some_file.txt')
print(f"文件是否存在:{exists}")

3.2 sys模块

import sys

# 获取Python版本
print(f"Python版本:{sys.version}")

# 获取命令行参数
print(f"命令行参数:{sys.argv}")

# 退出程序
# sys.exit(0)  # 正常退出

# 获取模块搜索路径
print(f"模块搜索路径:{sys.path}")

3.3 datetime模块

from datetime import datetime, date, timedelta

# 获取当前日期时间
now = datetime.now()
print(f"当前时间:{now}")

# 格式化日期
formatted = now.strftime("%Y-%m-%d %H:%M:%S")
print(f"格式化时间:{formatted}")

# 日期计算
tomorrow = now + timedelta(days=1)
print(f"明天:{tomorrow}")

# 创建特定日期
birthday = date(1990, 5, 15)
print(f"生日:{birthday}")

3.4 random模块

import random

# 生成随机整数
rand_int = random.randint(1, 10)
print(f"1-10的随机整数:{rand_int}")

# 生成随机浮点数
rand_float = random.random()
print(f"0-1的随机浮点数:{rand_float}")

# 从列表中随机选择
colors = ['red', 'green', 'blue']
rand_color = random.choice(colors)
print(f"随机颜色:{rand_color}")

# 打乱列表顺序
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(f"打乱后的列表:{numbers}")

3.5 json模块

import json

# Python对象转JSON字符串
data = {
    "name": "Alice",
    "age": 25,
    "skills": ["Python", "JavaScript", "SQL"]
}
json_str = json.dumps(data, indent=2)
print("JSON字符串:")
print(json_str)

# JSON字符串转Python对象
parsed_data = json.loads(json_str)
print(f"解析后的数据:{parsed_data}")

# 读写JSON文件
# 写入
with open('data.json', 'w') as f:
    json.dump(data, f, indent=2)

# 读取
with open('data.json', 'r') as f:
    loaded_data = json.load(f)
    print(f"从文件加载:{loaded_data}")

4. 包的概念

4.1 什么是包

包是一种用"点式模块名"构造Python模块命名空间的方法。包是包含特殊文件__init__.py的目录,可以包含模块和子包。

4.2 创建包

创建如下目录结构:

my_package/
│── __init__.py
│── module1.py
│── module2.py
│── subpackage/
│   ├── __init__.py
│   └── submodule.py

4.3 包的初始化文件

my_package/__init__.py

# 包级别的初始化代码
print("Initializing my_package")

# 定义包级别的变量
PACKAGE_VERSION = "1.0.0"

# 控制从包中导入的内容
__all__ = ["module1", "module2"]

4.4 使用包

# 导入包中的模块
import my_package.module1
from my_package import module2
from my_package.subpackage import submodule

# 使用包中的内容
my_package.module1.some_function()

5. pip包管理工具

5.1 基本命令

# 安装包
pip install package_name

# 安装指定版本
pip install package_name==1.0.0

# 升级包
pip install --upgrade package_name

# 卸载包
pip uninstall package_name

# 查看已安装的包
pip list

# 查看包的信息
pip show package_name

# 搜索包
pip search package_name

5.2 使用requirements.txt

创建requirements.txt文件:

numpy==1.21.0
pandas>=1.3.0
requests~=2.26.0
matplotlib

安装依赖:

pip install -r requirements.txt

生成requirements.txt:

pip freeze > requirements.txt

5.3 虚拟环境中的pip

# 创建虚拟环境
python -m venv myenv

# 激活虚拟环境
# Windows
myenv\Scripts\activate
# macOS/Linux
source myenv/bin/activate

# 在虚拟环境中安装包
pip install package_name

# 退出虚拟环境
deactivate

6. 创建自定义模块

6.1 实用工具模块

创建string_utils.py

# string_utils.py

def reverse_string(s):
    """反转字符串"""
    return s[::-1]

def is_palindrome(s):
    """检查字符串是否为回文"""
    s = s.lower().replace(" ", "")
    return s == s[::-1]

def count_words(text):
    """统计文本中的单词数量"""
    words = text.split()
    return len(words)

def capitalize_words(text):
    """将文本中每个单词的首字母大写"""
    return ' '.join(word.capitalize() for word in text.split())

# 模块测试
if __name__ == "__main__":
    test_string = "A man a plan a canal Panama"
    print(f"原始字符串:{test_string}")
    print(f"反转:{reverse_string(test_string)}")
    print(f"是回文:{is_palindrome(test_string)}")
    print(f"单词数:{count_words(test_string)}")
    print(f"首字母大写:{capitalize_words(test_string)}")

6.2 数据处理模块

创建data_processor.py

# data_processor.py

import json
import csv

def read_json_file(filename):
    """读取JSON文件"""
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"文件 {filename} 未找到")
        return None
    except json.JSONDecodeError:
        print(f"文件 {filename} 不是有效的JSON格式")
        return None

def write_json_file(data, filename, indent=2):
    """写入JSON文件"""
    with open(filename, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=indent, ensure_ascii=False)

def read_csv_file(filename):
    """读取CSV文件"""
    data = []
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            for row in reader:
                data.append(dict(row))
        return data
    except FileNotFoundError:
        print(f"文件 {filename} 未找到")
        return None

def calculate_statistics(numbers):
    """计算数字列表的统计信息"""
    if not numbers:
        return None
    
    stats = {
        'count': len(numbers),
        'sum': sum(numbers),
        'min': min(numbers),
        'max': max(numbers),
        'average': sum(numbers) / len(numbers)
    }
    
    # 计算中位数
    sorted_nums = sorted(numbers)
    n = len(sorted_nums)
    if n % 2 == 0:
        stats['median'] = (sorted_nums[n//2-1] + sorted_nums[n//2]) / 2
    else:
        stats['median'] = sorted_nums[n//2]
    
    return stats

7. 创建自定义包

7.1 创建完整的包结构

my_toolkit/
│── __init__.py
│── math_tools/
│   ├── __init__.py
│   ├── calculator.py
│   └── statistics.py
│── text_tools/
│   ├── __init__.py
│   ├── formatter.py
│   └── analyzer.py
│── file_tools/
│   ├── __init__.py
│   ├── reader.py
│   └── writer.py
└── setup.py

7.2 包的初始化文件

my_toolkit/__init__.py

"""
My Toolkit - 一个实用的Python工具包

这个包提供了数学计算、文本处理和文件操作的工具。
"""

__version__ = "1.0.0"
__author__ = "Your Name"

# 从子包中导入常用功能
from .math_tools.calculator import add, multiply
from .text_tools.formatter import capitalize_words
from .file_tools.reader import read_json_file

# 定义__all__控制from my_toolkit import *的行为
__all__ = [
    'add', 'multiply', 'capitalize_words', 'read_json_file'
]

7.3 子模块实现

my_toolkit/math_tools/calculator.py

def add(a, b):
    """加法运算"""
    return a + b

def subtract(a, b):
    """减法运算"""
    return a - b

def multiply(a, b):
    """乘法运算"""
    return a * b

def divide(a, b):
    """除法运算"""
    if b == 0:
        raise ValueError("除数不能为0")
    return a / b

def power(base, exponent):
    """幂运算"""
    return base ** exponent

7.4 创建setup.py

# setup.py
from setuptools import setup, find_packages

setup(
    name="my-toolkit",
    version="1.0.0",
    author="Your Name",
    author_email="your.email@example.com",
    description="A useful Python toolkit",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/yourusername/my-toolkit",
    packages=find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
    install_requires=[
        # 依赖列表
    ],
)

8. 常用第三方包

8.1 数据处理

# NumPy - 数值计算
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(f"数组:{arr}")
print(f"平均值:{np.mean(arr)}")

# Pandas - 数据分析
import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [25, 30, 35],
    'score': [85, 92, 78]
})
print(df.describe())

8.2 网络请求

# Requests - HTTP请求
import requests

response = requests.get('https://api.github.com')
print(f"状态码:{response.status_code}")
print(f"响应头:{response.headers}")

# 发送POST请求
data = {'key': 'value'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.json())

8.3 Web开发

# Flask - 轻量级Web框架
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def hello():
    return jsonify({'message': 'Hello, World!'})

if __name__ == '__main__':
    app.run(debug=True)

8.4 机器学习

# Scikit-learn - 机器学习
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# 加载数据
iris = load_iris()
X, y = iris.data, iris.target

# 分割数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# 训练模型
model = LogisticRegression()
model.fit(X_train, y_train)

# 预测
accuracy = model.score(X_test, y_test)
print(f"准确率:{accuracy}")

9. 模块搜索路径

9.1 查看搜索路径

import sys

# 查看模块搜索路径
for path in sys.path:
    print(path)

9.2 添加搜索路径

import sys

# 临时添加路径
sys.path.append('/path/to/your/module')

# 永久添加路径
# 1. 设置PYTHONPATH环境变量
# 2. 将模块放在site-packages目录中
# 3. 创建.pth文件

9.3 模块的查找顺序

  1. 当前目录
  2. PYTHONPATH环境变量中的目录
  3. Python标准库目录
  4. .pth文件中列出的目录
  5. 第三方库site-packages目录

10. 实践练习

10.1 练习1:创建实用工具模块

# 创建date_utils.py模块
from datetime import datetime, timedelta
import calendar

def get_days_in_month(year, month):
    """获取指定月份的天数"""
    return calendar.monthrange(year, month)[1]

def is_weekend(date_str):
    """判断指定日期是否为周末"""
    date_obj = datetime.strptime(date_str, "%Y-%m-%d")
    return date_obj.weekday() >= 5

def add_business_days(start_date, days):
    """添加工作日(跳过周末)"""
    current_date = datetime.strptime(start_date, "%Y-%m-%d")
    business_days_added = 0
    
    while business_days_added < days:
        current_date += timedelta(days=1)
        if current_date.weekday() < 5:  # 周一到周五
            business_days_added += 1
    
    return current_date.strftime("%Y-%m-%d")

def get_quarter(date_str):
    """获取日期所在的季度"""
    date_obj = datetime.strptime(date_str, "%Y-%m-%d")
    month = date_obj.month
    return (month - 1) // 3 + 1

# 测试代码
if __name__ == "__main__":
    print(f"2024年2月有{get_days_in_month(2024, 2)}天")
    print(f"2024-03-15是周末:{is_weekend('2024-03-15')}")
    print(f"从2024-03-11开始,添加5个工作日:{add_business_days('2024-03-11', 5)}")
    print(f"2024-03-15所在的季度:Q{get_quarter('2024-03-15')}")

10.2 练习2:创建数据处理包

# 创建data_toolkit包

# data_toolkit/__init__.py
"""
数据处理工具包
提供数据清洗、转换和分析的功能
"""

__version__ = "1.0.0"

from .cleaner import remove_duplicates, fill_missing
from .transformer import normalize, standardize
from .analyzer import summary_stats, correlation_matrix

# data_toolkit/cleaner.py
def remove_duplicates(data, key=None):
    """移除重复数据"""
    if key is None:
        return list(set(data))
    else:
        seen = set()
        result = []
        for item in data:
            identifier = item[key] if isinstance(item, dict) else getattr(item, key)
            if identifier not in seen:
                seen.add(identifier)
                result.append(item)
        return result

def fill_missing(data, fill_value=0):
    """填充缺失值"""
    if isinstance(data, list):
        return [fill_value if x is None else x for x in data]
    elif isinstance(data, dict):
        return {k: fill_value if v is None else v for k, v in data.items()}

# data_toolkit/transformer.py
def normalize(data):
    """归一化数据到0-1范围"""
    min_val = min(data)
    max_val = max(data)
    range_val = max_val - min_val
    if range_val == 0:
        return [0] * len(data)
    return [(x - min_val) / range_val for x in data]

def standardize(data):
    """标准化数据(Z-score)"""
    mean = sum(data) / len(data)
    variance = sum((x - mean) ** 2 for x in data) / len(data)
    std_dev = variance ** 0.5
    if std_dev == 0:
        return [0] * len(data)
    return [(x - mean) / std_dev for x in data]

# data_toolkit/analyzer.py
def summary_stats(data):
    """计算汇总统计信息"""
    if not data:
        return None
    
    stats = {
        'count': len(data),
        'min': min(data),
        'max': max(data),
        'mean': sum(data) / len(data)
    }
    
    sorted_data = sorted(data)
    n = len(sorted_data)
    if n % 2 == 0:
        stats['median'] = (sorted_data[n//2-1] + sorted_data[n//2]) / 2
    else:
        stats['median'] = sorted_data[n//2]
    
    # 计算标准差
    mean = stats['mean']
    variance = sum((x - mean) ** 2 for x in data) / n
    stats['std_dev'] = variance ** 0.5
    
    return stats

def correlation_matrix(data):
    """计算相关系数矩阵(简化版)"""
    # 这里仅作示例,实际应用中需要更复杂的实现
    n_features = len(data[0]) if data else 0
    matrix = [[0 for _ in range(n_features)] for _ in range(n_features)]
    
    for i in range(n_features):
        matrix[i][i] = 1.0  # 对角线为1
    
    return matrix

# 测试代码
if __name__ == "__main__":
    # 测试数据清洗
    data = [1, 2, 2, 3, 4, 4, 5]
    cleaned = remove_duplicates(data)
    print(f"去重后:{cleaned}")
    
    # 测试数据转换
    data = [1, 2, 3, 4, 5]
    normalized = normalize(data)
    print(f"归一化:{normalized}")
    
    standardized = standardize(data)
    print(f"标准化:{standardized}")
    
    # 测试数据分析
    stats = summary_stats(data)
    print(f"统计信息:{stats}")

总结

本章深入介绍了Python模块和包的使用,包括:

  • 模块的概念、创建和导入方法
  • Python标准库中常用模块的使用
  • 包的结构和创建方法
  • pip包管理工具的高级用法
  • 自定义模块和包的开发
  • 常用第三方包的介绍
  • 模块搜索路径的管理

掌握模块和包的使用是Python编程的重要技能,能够帮助你更好地组织代码、复用功能和管理项目依赖。

更多推荐