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

Python项目结构

Python项目结构

从哪些地方描述:

  • 分别描述两种目录结构
  • 两种目录结构的比较与区别
  • 当前采用的结构

由于 Python 简单易用,很多开始使用 Python 的人都是从一个脚本文件开始,逐步形成多个 Python 文件组成的

程序。也正因为如此大部分人并没以一个项目或工程的概念去看待自己的程序。而现在社区中的流行项目也存在两

种不同的目录结构。

1、简单结构

Python项目打包文章中以一个简单项目结构演示了如何打包一个 Python 项目。

https://packaging.python.org/en/latest/tutorials/packaging-projects/

packaging_tutorial
├── LICENSE
├── README.md
├── example_pkg
│   └── __init__.py
├── pyproject.toml
└── tests

项目结构以根目录开始,作为项目的环境。因为,为了在开发中正常导入 example_pkg 中所有的东西,就需要将

项目根目录添加到 sys.path 中。这也就让项目根目录下的所有包都变成了可导入。当有多个同级包时,它们都

是扁平的散落在项目根目录。项目根目录下可能还存在其他非包目录,如 datadocs 等。如果需要本地引用

第三方库,也需要放到根目录,但第三方包并不是项目的子包,而是它的一个引用。这样做会造成职责混乱。

比如这样的一个项目:

tutorial
├── LICENSE
├── README.md
├── data
|   └── user.json
├── docs
│   └── history.md
├── user
│   └── __init__.py
├── views
│   └── __init__.py
├── requests            # 这是需要本地打包的第三方包
│   └── __init__.py
├── pyproject.toml
└── tests

当多个目录扁平的分布在项目根目录时,它们扮演者不同的功能,在开发上,会带了一定的混乱。而且在打包和测

试上也会带来一些不便。

在打包上,需要提供更多的配置排除不必要的目录,如 docs 或者其他不需要打包仅项目中的东西。

当使用可编辑安装( pip install -e . ) 时,会将项目根目录中的所有东西安装到环境中,包括一些不需要

的。

使用自动化测试 tox 工具无法检测安装之后的问题,因为这种目录环境可以直接使用环境中的包(项目根目录被

添加到 sys.path 中了)。

2、src 结构

Pypa 维护的示例项目中采用了一种更推荐的结构 src 结构。

https://github.com/pypa/sampleproject

sampleproject
├── data
├── src
|   └── sample
|       └── __init__.py
├── pyproject.toml
└── tests

六年前的这篇文章 Packaging a python library就详细阐述了使用 src 结构比简单结构的诸多优点。而现在也逐

渐被社区作为一个标准遵循。虽然社区中有大量老的项目依然采用简单布局,但新项目推荐使用 src 结构。

https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure

如下面这个示例项目结构:

sampleproject
├── data
│   └── user.json
├── docs
│   └── history.md
├── pyproject.toml
├── src
│   ├── requests
│   │   └── __init__.py
│   └── sample
│       ├── __init__.py
│       ├── user
│       │   └── __init__.py
│       └── views
│           └── __init__.py
├── tests
│   ├── __init__.py
│   ├── user
│   │   └── __init__.py
│   └── views
│       └── __init__.py
└── tox.ini

项目的包结构很清晰,在环境中只需要引入 src 目录,就可以轻松导入项目源代码。通过 pip install -e .

可编辑安装,也只会安装 src 中的包。管理起来更加清晰。

3、实践

下面以一个简单真实的项目来演示使用 src 组织项目

3.1 创建项目

创建项目:

mkdir sampleproject
cd sampleproject

初始化版本管理:

git init
# 如果没有全局用户名和邮箱,需要先配置
git config user.email example@example.com
git config user.name example

创建项目自述文件:

touch README.md

3.2 编写项目源代码

创建项目包:

mkdir src/sample_project
touch src/sample_project/__init__.py

初始化版本号:

# src/sample_project/__init__.py
__version__ = '0.1.0'

安装依赖:

# 安装click
poetry add click

创建命令入口文件:

# src/sample_project/cmdline.py
import click@click.command()
def main():click.echo('Hello world!')if __name__ == "__main__":main()

3.3 编写测试

创建测试目录:

mkdir -p tests/sample_project
# 高版本test不能添加__init__.py文件
touch tests/sample_project/__init__.py

安装依赖:

poetry add -D pytest

创建测试文件:

# tests/sample_project/test_cmdline.py
from click.testing import CliRunnerfrom sample_project import cmdlinedef test_main():runner = CliRunner()result = runner.invoke(cmdline.main)assert 'Hello world!' in result.output

运行测试:

pip install -e .  # 以可编辑安装方式到环境中
pytest

测试运行成功,说明功能正确

3.4 初始化打包配置

编写打包配置:

# pyproject.toml
[tool.poetry]
name = "sample_project"
version = "0.1.0"
description = "Sample Project"
readme = "README.md"
authors = ["example <example@example.com>"]
license = "MIT"
classifiers = ["Operating System :: OS Independent","Programming Language :: Python :: 3.10",
][tool.poetry.dependencies]
python = "^3.10"
click = "^8.1.3"[tool.poetry.dev-dependencies]
pytest = "^7.1.2"[tool.poetry.plugins."scripts"]
sample_project = "sample_project.cmdline:main"[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

打包:

poetry build

3.5 总结

至此,一个项目开发完成,完整项目结构如下:

├── dist
│   ├── sample_project-0.1.0.tar.gz 
|   └── sample_project-0.1.0-py3-none-any.whl
├── poetry.lock
├── pyproject.toml
├── src
│   └── sample_project
│       ├── cmdline.py
│       ├── __init__.py
└── tests├── __init__.py└── sample_project├── __init__.py└── test_cmdline.py
http://www.xdnf.cn/news/10547.html

相关文章:

  • 录屏不再难,从功能到体验深度测评
  • MPTCP 聚合吞吐
  • LRU和LFU缓存策略
  • ESP32系列AT固件快速开发——Wi-Fi MQTT
  • 【笔记】Windows系统部署suna基于 MSYS2的Poetry 虚拟环境backedn后端包编译失败处理
  • 汽车安全体系:FuSa、SOTIF、Cybersecurity 从理论到实战
  • 绿盟 IPS 设备分析操作手册
  • Nuxt3部署
  • TS 星际通信指南:从 TCP 到 UDP 的宇宙漫游
  • (Python)列表的操作(增删改查、排序)
  • 2025年ESWA SCI1区TOP,改进成吉思汗鲨鱼算法MGKSO+肝癌疾病预测,深度解析+性能实测
  • 网络攻防技术四:网络侦察技术
  • 重温经典算法——快速排序
  • 探秘集成学习:从基础概念到实战应用
  • 微软PowerBI考试 PL-300学习指南
  • DeepSeek 赋能车路协同:智能交通的破局与重构
  • 模块二:C++核心能力进阶(5篇) 篇一:《STL源码剖析:vector扩容策略与迭代器失效》
  • 核心机制:滑动窗口
  • 相机--相机标定
  • 芝麻酱工作创新点分享1——SpringBoot下使用mongo+Redis做向量搜索
  • PyTorch——卷积操作(2)
  • [网页五子棋][匹配对战]落子实现思路、发送落子请求、处理落子响应
  • Python 在金融中的应用- Part 1
  • JSP、HTML和Tomcat
  • Linux运维笔记:服务器感染 netools 病毒案例
  • Windows+VSCode搭建小智(xiaozhi)开发环境
  • 通信革新与网络安全探索与创新:开启未来之门
  • ShenNiusModularity项目源码学习(33:ShenNius.Admin.Mvc项目分析-18)
  • 【看到哪里写到哪里】C的指针-3(函数指针)
  • P1115 最大子段和