Python项目结构和打包
Python项目结构和打包
pip install 的本质
从 PyPI(默认)或其他源(如私有仓库、本地文件)查找指定名称的包,下载对应的.whl文件
whl文件
.whl是 Wheel 的缩写,是 Python 的一种标准打包格式(PEP 427 定义)。- 它本质上是一个 ZIP 格式的压缩包,扩展名改为
.whl。
安装 .whl 文件
1 | pip install package_name.whl |
hachling
hatchling 是 Python
生态中一个现代的、轻量级的构建后端(build
backend),主要用于将 Python 项目打包成可分发的格式(如
.whl 或源码包)。它是 Hatch项目的一部分,由 PyPA(Python
Packaging Authority)推荐使用。
在pyproject.toml添加
1 | [build-system] |
当你运行:
1 | pip install . |
如果项目配置了 hatchling 作为构建后端,pip
或 build 工具就会调用 hatchling
来完成打包和安装。
例如以下项目结构
1 | my_project/ |
想让项目的其他文件使用自己编写的包,在pyproject.toml增加
1 | # 👇 新增:显式声明包位置 |
在项目根目录(my_project/)执行:
1 | uv pip install -e . |
✅ 这会把
src/my_utils/注册为一个可导入的包。
src layout
src layout(也称为 src 布局 或
src 目录结构)是 Python
项目中一种推荐的源代码组织方式,其核心思想是:将你的
Python 包(package)放在一个名为 src/
的子目录下,而不是直接放在项目根目录中。
❌ 传统布局(不推荐)
1 | my_project/ |
✅ src 布局(推荐)
1 | my_project/ |
uv build和uv pip install .什么区别
一、uv build
✅ 作用:构建分发包(不安装)
- 调用项目的构建后端(如
hatchling、setuptools等)。 - 生成标准的分发文件:
- 一个 Wheel 文件(
.whl) - 一个 源码分发包(sdist,
.tar.gz)
- 一个 Wheel 文件(
- 输出到项目根目录下的
dist/文件夹。 - 不会将包安装到当前 Python 环境中。
🔧 示例:
1 | uv build |
输出: 1
2dist/my_package-0.1.0-py3-none-any.whl
dist/my_package-0.1.0.tar.gz
二、uv pip install .
✅ 作用:安装当前项目到当前环境
- 首先(隐式)构建项目(类似
uv build的过程)。 - 然后将构建结果安装到当前激活的 Python 环境(如虚拟环境或系统环境)。
- 安装后,你可以在 Python 中
import该包。 - 默认是 “非可编辑安装”(即代码改动不会自动生效,除非重新安装)。
🔧 示例:
1 | uv pip install . |
效果: - 包被安装到 site-packages/ - 可在 Python 中
import my_package
Editable install(可编辑安装)
Editable install(可编辑安装) 是 Python 包管理中的一种安装模式,它让你在安装一个包的同时,保留对源代码的直接引用。
1 | uv pip install -e . |
- 核心机制:
- 不复制代码到
site-packages/。 - 而是在
site-packages/中创建一个.pth文件 或my_package.egg-link,指向你本地项目中的src/(或包目录)。 - Python 解释器在导入时,会顺着这个链接去读你本地的源码。
- 不复制代码到
python是从哪里查找模块的
Python 查找模块(module)的机制由 模块搜索路径(module search
path) 决定,这个路径是一个字符串列表,存储在
sys.path 中。当你执行 import some_module
时,Python
会按顺序在这个列表中的每个目录里查找对应的模块文件。
可以通过以下代码查看当前 Python 的模块搜索路径:
1 | import sys |
sys.path 通常包含以下几类路径(顺序很重要):
- 脚本所在目录(或当前工作目录)
- 如果你运行
python /path/to/script.py,那么/path/to/会被加到sys.path[0]。 - 如果你运行
python进入交互模式,或运行python -c "...",则当前工作目录(os.getcwd()) 会被放在首位。 - ⚠️ 这是很多“意外导入”问题的根源(比如项目根目录下有同名包)。
- 环境变量
PYTHONPATH中的目录
- 类似系统的
PATH,你可以通过设置PYTHONPATH添加自定义搜索路径。 - 示例(Linux/macOS):
1
2export PYTHONPATH="/my/custom/modules:$PYTHONPATH"
python my_script.py - Windows(PowerShell):
1
$env:PYTHONPATH = "C:\my\custom\modules;" + $env:PYTHONPATH
- 标准库目录
- Python 自带的模块(如
os,sys,json)所在位置。 - 通常位于 Python 安装目录下的
lib/子目录中。
- 第三方包安装目录(site-packages)
- 通过
pip install、uv pip install等安装的包,会被放到site-packages目录。 - 路径可通过以下命令查看:
1
2
3import site
print(site.getsitepackages()) # 全局环境
print(site.getusersitepackages()) # 用户级安装
.pth文件中指定的路径
- 某些包(尤其是 editable install)会在
site-packages/中放置.pth文件,动态添加路径到sys.path。