python包管理
在archlinux上,安装python包有两种方式:
- 通过系统包管理器安装,比如
sudo pacman -S python-pandas
- 创建虚拟环境,在某个项目路径下使用pip安装到虚拟环境。也可通过uv等现代工具管理。 为了避免依赖冲突,我推荐在积累自己的代码时只用第2种方式。第1种方式只用于系统在安装软件时安装某些python依赖项,而不用于手动安装项目依赖的python包.
- 创建和使用虚拟环境的传统方法(推荐使用uv或poetry而不是这么做)
python -m venv .venv # 创建虚拟环境.venv
source .venv/bin/activate # 启用虚拟环境.venv
pip install pandas # 安装包到虚拟环境目录下(.venv/lib/pythonx.xx/site-packages)
pip freeze > requirements.txt # 导出当前虚拟环境下安装的包(主动安装的包和它们的依赖混在一起)
pip install -r requirements.txt # 通过包列表安装py包
- 代替requirements.txt – 现代python包管理的统一标准:pyproject.toml
[project]
name = "proj"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"pandas==2.3.1"
]
有了这个文件后下面的命令,会对当前项目进行打包,然后和依赖项一起安装到虚拟环境下
pip install -e . #使用-e是为了不将自己的源代码复制到虚拟环境,而只是创建链接,保证所有修改立即生效。
- 以上流程又需要手动查包的版本号,所以产生了更加方便的工具,比如uv,它能把以上创建虚拟环境和编辑
pyproject.toml
的流程自动化(只需要有个最初的包含项目版本号的pyproject.toml
文件)
uv add pandas # 把某个包添加到虚拟环境(不需要手动启动虚拟环境)
uv sync # 根据当前pyproject.toml文件搭建项目的虚拟环境
uv run main.py # 在当前路径虚拟环境的上下文中执行命令
python项目结构与打包
一般在用与包名相同的目录存放所有代码(flat layout)后,再把它放进src/
下(src layout)。
.
|_ doc/
|_ scratch/
|_ src/
|_ myproject/
|_ __init__.py # 项目的代码目录中,这个文件作为可导入包的标记
|_ test/
项目构建用工具
- frontend: build(官方工具,需要先安装)/ uv
- backend: setuptools (官方,历史包袱太重)/ hatchling
使用这hatchling需要在
pyproject.toml
中指定:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/myproject"]
这里"myproject"是项目中存放代码的路径名 构建的命令是
python -m build # 使用build
uv build # 使用uv
注意,如果使用build而不是uv,在开发阶段要执行一次以下命令,将项目本身链接到虚拟环境,这样能保证模块之间能通过相对路径import
pip install -e .
个人python函数的积累策略
个人函数库
只用一个库积累可复用性高的函数,分不同子包存放不同领域的python脚本。这个包需要发布到pypi上,方便在其他项目中使用。
~/workspace/lib/python/shadowslib/
├── .venv/
├── pyproject.toml
└── src/shadowslib/
├── __init__.py
└── data/ # 数据处理与画图
├── __init__.py
├── moudle1.py
├── moudle2.py
└── _archive/
└── ui/ # 人机交互
├── __init__.py
├── moudle1.py
├── moudle2.py
└── _archive/
└── ... # 其他分类
注:_archive/
路径用来存放写好后几乎没被用到过但又舍不得删的函数。
- 在
__init__.py
文件中,用__all__
这个列表变量选择要对外暴露的函数 _archive/
路径下没有__init__.py
文件,因此它不会被当成一个子包。
在其它项目中使用个人函数库
如果只是单独使用一个脚本,尽量不要引入shadowslib中不包含的依赖包。
对于一个没有引入额外依赖的且不会发布的python脚本
- 因为我们在
.bashrc
中,我们直接使用shadowslib
的虚拟环境的路径作为PYTHONPATH
,这样就可以在脚本中直接导入shadowslib
。
export PYTHONPATH=/home/shadows/workspace/lib/python/shadowslib/.venv/lib/python3.13/site-packages:$PYTHONPATH
- 所以可以在脚本中直接导入
shadowslib
,不需要包管理
from shadowslib.data import moudle1 from shadowslib.ui import moudle2
- 因为我们在
对于一个可能会发布的或会使用额外依赖的项目,要创建它自己的虚拟环境,并在其中使用
shadowslib
作为依赖。- 在项目目录下创建一个
pyproject.toml
文件,内容如下:
[project] name = "myproject" version = "0.1.0" requires-python = ">=3.13" dependencies = [ # 由于已经在.bashrc中设置了PYTHONPATH,所以可以直接导入shadowslib,而不用本地路径 # 其它人使用这个项目时,包管理工具会从pypi上下载shadowslib "shadowslib>=0.1.0" ]
- 然后在项目目录下执行以下命令安装依赖(也可以直接使用
uv run
命令来运行脚本)
uv sync
- 在项目目录下创建一个