当前位置: 首页 > news >正文

Day 35 文件的规范拆分和写法

@浙大疏锦行

Python 项目的文件规范拆分核心目标是:高内聚、低耦合(一个文件 / 模块只做一类事)、可读性强(命名和结构直观)、易维护扩展(逻辑分层清晰)。

一、文件拆分的核心原则

1. 单一职责原则(最核心)

一个文件 / 模块只负责一个核心功能:

  • 比如calc.py只放计算相关函数,log.py只放日志相关工具,models.py只定义数据类;
  • 避免 “万能文件”(如把所有功能都写在main.py里),单个文件代码量建议控制在 500 行以内(复杂模块可再拆分)。

2. 分层拆分原则

按 “功能层” 拆分,而非 “代码类型” 拆分,典型分层:

层级作用示例文件名
数据层定义数据结构 / 模型models.py/schemas.py
工具层通用工具函数 / 常量utils.py/constants.py
业务层核心业务逻辑service.py/handler.py
入口层程序启动 / 命令执行main.py/run.py
配置层配置项 / 环境变量config.py/settings.py

3. 命名规范原则

文件 / 目录名直接体现功能,拒绝模糊命名:

  • 文件名:全小写 + 下划线分隔(snake_case),如user_service.py而非UserService.py/userservice.py
  • 目录名:全小写,简洁通用,如utils/core/api/data,避免拼音 / 特殊字符;
  • 避免重复命名:如不要同时有utils.pyutils/目录(易混淆)。

4. 依赖最小原则

模块间尽量减少 “循环依赖”,比如:

  • 工具层不依赖业务层(工具函数应通用,不耦合具体业务);
  • 配置层只提供常量 / 配置,不依赖其他层。

二、通用项目目录结构规范

不同规模项目的拆分粒度不同,以下是从 “小型脚本” 到 “中型项目” 的演进结构:

1. 小型项目(单功能脚本,1000 行内)

适合单个功能(如数据处理、小工具),核心是 “少而精”:

my_tool/ ├── main.py # 程序入口(调用核心逻辑) ├── utils.py # 通用工具函数(如文件读写、数据转换) ├── config.py # 配置项(如文件路径、常量) └── README.md # 说明文档(功能、使用方法)

2. 中型项目(多功能业务,1000-10000 行)

适合有明确业务逻辑的项目(如管理系统、爬虫、数据分析),按 “目录 + 文件” 分层:

my_project/ ├── my_project/ # 核心包(项目名,避免与第三方库重名) │ ├── __init__.py # 包标识(可定义导出接口) │ ├── config/ # 配置层 │ │ ├── __init__.py │ │ └── settings.py # 配置项 │ ├── models/ # 数据层 │ │ ├── __init__.py │ │ └── user.py # 用户数据模型 │ ├── utils/ # 工具层 │ │ ├── __init__.py │ │ ├── file_utils.py # 文件操作工具 │ │ └── log_utils.py # 日志工具 │ └── core/ # 业务层 │ ├── __init__.py │ └── user_service.py # 用户业务逻辑 ├── main.py # 程序入口(启动/调用业务逻辑) ├── requirements.txt # 依赖清单(如 pandas==2.0.0) └── README.md # 项目说明

3. 关键补充:__init__.py的写法

__init__.py是 Python 包的标识文件,核心作用:

  • 空文件:仅标识目录为包(基础功能);
  • 定义__all__:控制from 包 import *时导入的模块 / 属性,如:
    # my_project/core/__init__.py __all__ = ["user_service"] # 仅导出user_service模块
  • 简化导入:将子模块的核心内容导入包层级,方便外部调用,如:
    # my_project/core/__init__.py from .user_service import UserService # 从子模块导入类
    外部调用时可直接from my_project.core import UserService,而非from my_project.core.user_service import UserService

三、文件内部的写法规范

1. 代码结构(从上到下)

单个文件内按 “固定顺序” 组织代码,提升可读性:

# 1. 导入模块(按PEP8规范排序) # 1.1 标准库导入(优先) import os import sys from datetime import datetime # 1.2 第三方库导入 import pandas as pd import requests # 1.3 自定义模块导入 from my_project.config.settings import BASE_DIR from my_project.utils.file_utils import read_file # 2. 常量定义(全大写+下划线) MAX_RETRY = 3 DEFAULT_ENCODING = "utf-8" DATA_PATH = os.path.join(BASE_DIR, "data") # 3. 类定义(大驼峰命名) class User: """用户数据模型(文档字符串说明)""" def __init__(self, name: str, age: int): self.name = name self.age = age def get_info(self) -> str: """获取用户信息""" return f"姓名:{self.name},年龄:{self.age}" # 4. 函数定义(小写+下划线) def validate_user(user: User) -> bool: """验证用户信息是否合法""" if not user.name or user.age < 0: return False return True # 5. 主逻辑(仅入口文件需要,其他文件避免顶层执行代码) if __name__ == "__main__": user = User("Alice", 18) print(validate_user(user))

2. 关键规范

(1)导入规范
  • 导入顺序:标准库 → 第三方库 → 自定义库(用空行分隔);
  • 避免导入未使用的模块(可通过flake8工具检查);
  • 自定义模块导入优先用绝对路径,避免相对路径(如from my_project.utils import read_file而非from ..utils import read_file)。
(2)注释规范
  • 模块级注释:文件顶部写清楚 “该文件的作用、适用场景、核心功能”;
  • 类 / 函数注释:用文档字符串(""")说明功能、参数、返回值(推荐 Google 风格);
  • 行内注释:仅解释 “为什么这么写”,而非 “写了什么”(如# 重试3次避免网络抖动而非# 循环3次)。
(3)避免顶层执行代码(非入口文件)

除了main.py/run.py等入口文件,其他模块应避免 “导入即执行” 的代码,比如:

# 错误示例(utils.py):导入时会自动执行print print("加载工具模块") def add(a, b): return a + b # 正确做法:将执行代码放在if __name__ == "__main__"中 if __name__ == "__main__": print("加载工具模块") # 仅直接运行该文件时执行,导入时不执行
(4)类型注解(可选但推荐)

为函数 / 类的参数、返回值添加类型注解,提升可读性和可维护性:

def calculate_area(radius: float) -> float: """计算圆的面积""" import math return math.pi * radius **2

四、实战示例:从 “混乱脚本” 到 “规范拆分”

原始混乱脚本(all_in_one.py)

# 所有功能写在一个文件,无拆分 import os import math # 配置项 DATA_DIR = "./data" PI = math.pi # 数据模型 class Circle: def __init__(self, radius): self.radius = radius # 工具函数 def read_data(file_path): with open(file_path, "r") as f: return f.read() # 业务逻辑 def calculate_circle_area(radius): return PI * radius **2 # 主逻辑 if __name__ == "__main__": circle = Circle(5) area = calculate_circle_area(circle.radius) print(f"圆面积:{area}") read_data(os.path.join(DATA_DIR, "circle.txt"))

规范拆分后

目录结构
circle_calc/ ├── circle_calc/ │ ├── __init__.py │ ├── config.py # 配置层 │ ├── models.py # 数据层 │ ├── utils.py # 工具层 │ └── core.py # 业务层 ├── main.py # 入口层 └── README.md
各文件写法
  1. circle_calc/config.py(配置层)
"""配置文件:定义项目常量和路径""" import os import math # 路径配置 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DATA_DIR = os.path.join(BASE_DIR, "data") # 常量配置 PI = math.pi MAX_RADIUS = 100 # 最大半径限制
  1. circle_calc/models.py(数据层)
"""数据模型:定义几何图形类""" from .config import MAX_RADIUS class Circle: """圆数据模型,包含半径属性和合法性校验""" def __init__(self, radius: float): if not self._validate_radius(radius): raise ValueError(f"半径必须大于0且小于等于{MAX_RADIUS}") self.radius = radius @staticmethod def _validate_radius(radius: float) -> bool: """校验半径合法性""" return isinstance(radius, (int, float)) and 0 < radius <= MAX_RADIUS
  1. circle_calc/utils.py(工具层)
"""工具函数:通用文件操作""" import os from .config import DEFAULT_ENCODING DEFAULT_ENCODING = "utf-8" def read_data(file_path: str) -> str: """读取文件内容,处理常见IO异常""" try: with open(file_path, "r", encoding=DEFAULT_ENCODING) as f: return f.read() except FileNotFoundError: raise FileNotFoundError(f"文件不存在:{file_path}") except PermissionError: raise PermissionError(f"无权限读取文件:{file_path}")
  1. circle_calc/core.py(业务层)
"""核心业务:几何图形计算逻辑""" from .models import Circle from .config import PI def calculate_circle_area(circle: Circle) -> float: """计算圆的面积(接收Circle对象,返回面积)""" return PI * circle.radius **2
  1. circle_calc/__init__.py(包导出)
"""圆面积计算工具包""" from .core import calculate_circle_area from .models import Circle __all__ = ["calculate_circle_area", "Circle"] # 定义导出接口
  1. main.py(入口层)
"""程序入口:执行圆面积计算逻辑""" from circle_calc import Circle, calculate_circle_area from circle_calc.config import DATA_DIR from circle_calc.utils import read_data import os def main(): """主函数:封装核心执行逻辑""" # 1. 创建圆对象 try: circle = Circle(5) except ValueError as e: print(f"创建圆失败:{e}") return # 2. 计算面积 area = calculate_circle_area(circle) print(f"半径为{circle.radius}的圆面积:{area:.2f}") # 3. 读取数据文件 try: data = read_data(os.path.join(DATA_DIR, "circle.txt")) print(f"数据文件内容:{data}") except Exception as e: print(f"读取文件失败:{e}") if __name__ == "__main__": main()
http://www.jsqmd.com/news/74154/

相关文章:

  • 【Dify 1.7.0多模态RAG音频处理】:揭秘新一代AI语音理解核心技术
  • Wan2.2-T2V-A14B模型在高校数字媒体教学中的引入方案
  • HBase vs. 传统数据库:大数据时代的存储革命
  • Wan2.2-T2V-A14B如何实现季节变换的自然过渡?春去秋来效果演示
  • 【OD刷题笔记】- 分积木
  • 经典算法题详解之游乐园的迷宫(二)
  • 终极解决方案:JetBrains IDE试用期一键重置完整指南
  • 【限时掌握】Docker Scout AI漏洞检测功能全解析,错过再等一年
  • 智能计算模拟:第一性原理+分子动力学+机器学习
  • 阿里达摩院Qwen3-VL多模态模型重磅发布:开启视觉-语言交互新纪元
  • 腾讯混元开源四梯度轻量模型:开启端侧AI普惠新时代
  • VBA-JSON终极指南:快速掌握Excel和Access中的JSON数据处理
  • 重磅发布:Qwen3-VL-8B-Instruct多模态大模型开源,开启智能视觉交互新纪元
  • 第九章: I²C 模块 —— 给你的芯片装上“微信”!
  • Wan2.2-T2V-A14B支持绿幕抠像输出吗?后期合成兼容性探讨
  • 【稀缺技术曝光】:VSCode+量子计算远程调试完整配置方案首次公开
  • 开源模型性能革命:Qwen3-0.6B碾压Gemma4B,235B旗舰版代码能力逼近Claude3.5
  • 70亿参数推动企业智能化转型:Granite-4.0-H-Tiny如何解决AI落地成本难题
  • Wan2.2-T2V-A14B实现物理级动态模拟的三大核心技术
  • Universal x86 Tuning Utility:解锁Intel处理器隐藏性能的终极方案
  • 重新定义视频管理:易元AI如何用“智能分镜”将你的视频库变成可搜索的资产
  • ACPI!ACPIInitialize函数分析之替换中断对象的地址
  • Wan2.2-T2V-A14B能否生成微观世界放大动画?生物学教学辅助
  • 开源AI智能名片链动2+1模式商城小程序在淘宝首页流量生态中的应用与影响研究
  • 基于AI智能客服与AI智能名片商城系统的社群客服培养机制及优化策略研究
  • 2026年机器人感知与智能控制国际学术会议(RPIC 2026)
  • 人工智能如何重塑未来工作格局:机遇与挑战并存的职场新生态
  • Wan2.2-T2V-A14B如何应对极寒环境下的材质收缩形变
  • Agentic AI技术革命:提示工程架构师的实战指南
  • 基于java的SpringBoot/SSM+Vue+uniapp的建金粮食供应链管理系统的详细设计和实现(源码+lw+部署文档+讲解等)