uv工程化项目指南

UV 工程化项目完整指南

目录

  1. 预备知识:两种项目类型
  2. 类型一:工具包(Library)
  3. 类型二:有入口的应用(Application)
  4. [pyproject.toml 配置速查表](#pyproject.toml 配置速查表)
  5. 打包(Build)
  6. 运行与部署
  7. 两种类型对比总结
  8. FAQ

预备知识:两种项目类型

类型 特点 使用方式 场景
工具包(Library) 只提供 import,无入口 from xxx import yyy SDK、工具函数库、框架
应用(Application) 有 CLI 命令或可 python -m 终端敲命令 CLI 工具、Web 服务、脚本入口

类型一:工具包(Library)

项目结构

复制代码
demo_lib/
├── pyproject.toml          ← 项目配置
├── README.md
├── .python-version
└── src/
    └── greetlib/           ← 包名 = 导入名
        ├── __init__.py     ← 暴露公开 API
        ├── py.typed        ← 类型标注标记
        └── greeter.py      ← 核心业务模块

各文件内容

pyproject.toml
toml 复制代码
[project]
name = "greetlib"                            # pip install / uv add 用的名字
version = "0.1.0"                            # 语义化版本
description = "A simple greeting library"
readme = "README.md"
requires-python = ">=3.10"                   # 最低 Python 版本
dependencies = []                            # 运行时依赖(自动安装)

[project.optional-dependencies]              # pip install greetlib[dev]
dev = ["pytest>=7"]

[project.urls]                               # PyPI 页面上显示的链接
Homepage = "https://github.com/example/greetlib"

[build-system]                               # 构建后端(告诉 uv 用什么打包)
requires = ["uv_build>=0.11.15,<0.12.0"]
build-backend = "uv_build"
src/greetlib/init.py
python 复制代码
"""Public API of greetlib."""

from greetlib.greeter import greet, greet_many

__all__ = ["greet", "greet_many"]

作用:控制 from greetlib import xxx 能拿到什么。

src/greetlib/greeter.py
python 复制代码
"""Core greeting logic."""


def greet(name: str) -> str:
    """Return a greeting string."""
    return f"Hello, {name}!"


def greet_many(names: list[str]) -> list[str]:
    """Greet multiple people."""
    return [greet(name) for name in names]
src/greetlib/py.typed

空文件。标记这个包有类型注解。


类型二:有入口的应用(Application)

项目结构

复制代码
demo_app/
├── pyproject.toml
├── README.md
├── .python-version
└── src/
    └── greetapp/
        ├── __init__.py       ← 包标记(可为空)
        ├── __main__.py       ← python -m greetapp 入口
        └── cli.py            ← CLI 实际逻辑

各文件内容

pyproject.toml
toml 复制代码
[project]
name = "greetapp"
version = "0.1.0"
description = "A greeting CLI application"
readme = "README.md"
requires-python = ">=3.10"
dependencies = []

[project.optional-dependencies]
dev = ["pytest>=7"]

[project.urls]
Homepage = "https://github.com/example/greetapp"

# ★ 命令行入口,安装后终端直接打 greetapp 就跑
# 格式:命令名 = "模块:函数名"
[project.scripts]
greetapp = "greetapp.cli:main"

[build-system]
requires = ["uv_build>=0.11.15,<0.12.0"]
build-backend = "uv_build"
src/greetapp/init.py
python 复制代码
"""greetapp package marker."""

空文件,标记该目录为一个 Python 包。

src/greetapp/main.py
python 复制代码
"""Entry point for `python -m greetapp`."""

from greetapp.cli import main

if __name__ == "__main__":
    main()

作用:支持 python -m greetapp 运行。

src/greetapp/cli.py
python 复制代码
"""CLI entry point."""


def main() -> None:
    """Print a greeting."""
    print("Hello from greetapp!")
    print("Usage: greetapp <name>")

两种入口方式对比

方式 配置文件/模块 运行命令
python -m 同目录下的 __main__.py python -m greetapp
CLI 命令 pyproject.toml[project.scripts] 终端直接打 greetapp

两者不冲突,可以同时存在。


pyproject.toml 配置速查表

配置段 作用 Library Application
[project] 包名、版本、描述、Python 版本、运行时依赖 必填 必填
[project.scripts] 定义命令行命令(应用专属) 不需要 按需
[project.optional-dependencies] 可选依赖分组(如 dev/test/docs) 按需 按需
[project.urls] 项目链接(PyPI 页面上显示) 推荐 推荐
[build-system] 声明构建后端,两行固定写法 必填 必填

打包(Build)

bash 复制代码
cd demo_lib                          # 进入项目目录
uv build                             # 生成 .whl + .tar.gz 到 dist/

cd demo_app                          # 应用项目也一样
uv build

产物在 dist/ 目录下:

复制代码
dist/
├── greetlib-0.1.0-py3-none-any.whl     ← 分发包(主用)
└── greetlib-0.1.0.tar.gz               ← 源码包

运行与部署

一、开发时调试(打包前)

在项目目录里直接运行,不需要打包:

bash 复制代码
uv run greetapp                     # 走 [project.scripts] 配置
uv run python -m greetapp           # 走 __main__.py

uv 会自动管理虚拟环境,无需手动激活。

二、打包后验证(不安装)

打好包后想确认 whl 是否正确,不想污染任何环境

方法 1 ------ uv run --with(最常用):

bash 复制代码
# 应用:跑 CLI 命令
uv run --with ./dist/greetapp-0.1.0-py3-none-any.whl greetapp

# 库:验证 import
uv run --with ./dist/greetlib-0.1.0-py3-none-any.whl python -c \
    "from greetlib import greet; print(greet('World'))"

uv 自动创建临时虚拟环境安装 whl,跑完就清理。

方法 2 ------ uv tool run --from(语义更清晰,效果一样):

bash 复制代码
uv tool run --from ./dist/greetapp-0.1.0-py3-none-any.whl greetapp

方法 3 ------ 直接解压 whl(了解原理):

bash 复制代码
# whl 本质就是 zip 文件
cd /tmp
unzip ../dist/greetapp-0.1.0-py3-none-any.whl -d greetapp_tmp
PYTHONPATH=/tmp/greetapp_tmp python -c "from greetapp.cli import main; main()"

不推荐日常用,只是说明 whl 并非黑盒。

三、正式环境部署运行

生产环境需要稳定、可重复、能自愈。以下是四种常见方案:

方案 A:全局安装 CLI 工具

适用场景:脚本类工具,不依赖具体项目。

bash 复制代码
# 安装(只需一次)
uv tool install greetapp-0.1.0-py3-none-any.whl

# 之后任何目录下直接执行
greetapp

本质:uv 将 whl 装到其全局工具目录,生成可执行文件到 PATH,与项目依赖隔离。

方案 B:专属虚拟环境(服务/常驻进程)

适用场景:Web 服务、后台任务、需要进程管理的应用。

bash 复制代码
# 1. 复制 whl 到服务器,创建专属虚拟环境
uv venv /opt/greetapp/.venv

# 2. 把 whl 安装进去
linux安装:/opt/greetapp/.venv/bin/pip install greetapp-0.1.0-py3-none-any.whl
windows安装:uv pip install --python \opt\greetapp\.venv D:\pycharmworkspace\PythonwebProject\dist\testlib-0.1.0-py3-none-any.whl

# 3. 用 systemd 管理进程
windows运行:/opt/greetapp/.venv/Scripts/python -m testlib
linux运行:/opt/greetapp/.venv/bin/python -m testlib

systemd 配置(/etc/systemd/system/greetapp.service):

ini 复制代码
[Unit]
Description=greetapp service
After=network.target

[Service]
Type=simple
ExecStart=/opt/greetapp/.venv/bin/greetapp
Restart=always
User=greetapp
Group=greetapp

[Install]
WantedBy=multi-user.target
bash 复制代码
# 启动
systemctl start greetapp
systemctl enable greetapp    # 开机自启

如果没有 systemd(如老旧发行版),可用 supervisor:

ini 复制代码
[program:greetapp]
command=/opt/greetapp/.venv/bin/greetapp
autostart=true
autorestart=true
user=greetapp
方案 C:Docker 容器化(最推荐)

适用场景:任何正式环境,特别是微服务、云原生部署。

dockerfile 复制代码
FROM python:3.12-slim

COPY greetapp-0.1.0-py3-none-any.whl /app/
RUN pip install /app/greetapp-0.1.0-py3-none-any.whl

CMD ["greetapp"]
bash 复制代码
# 构建
docker build -t greetapp .

# 运行
docker run greetapp

# 或 docker-compose.yml
yaml 复制代码
version: "3"
services:
  greetapp:
    build: .
    restart: always

Docker 的好处:环境完全一致、依赖隔离、无需手动管理 venv 和进程。

方案 D:极简环境(无 Docker 无 systemd)
bash 复制代码
# 创建并使用 venv
python3 -m venv /opt/greetapp/venv
/opt/greetapp/venv/bin/pip install greetapp-0.1.0-py3-none-any.whl

# 写到 crontab 或 rc.local
/opt/greetapp/venv/bin/greetapp

四、让其他项目使用已打好的包

方式 1 ------ 直接装 whl 文件:

bash 复制代码
uv add ./dist/greetlib-0.1.0-py3-none-any.whl

方式 2 ------ 安装本地项目目录:

bash 复制代码
uv add /path/to/demo_lib               # 只读安装

方式 3 ------ 可编辑安装(改源码即时生效,开发时用):

bash 复制代码
uv add -e /path/to/demo_lib

方式 4 ------ 发布到 PyPI,全世界都能装:

bash 复制代码
uv publish
# 别人就能:uv add greetlib

五、运行方式对比总表

阶段 方式 命令 适用场景
开发调试 uv run <cmd> uv run greetapp 未打包,在项目目录内
打包验证 uv run --with ./xxx.whl <cmd> 一行命令,临时环境 本地测试 whl 是否正确
生产-小工具 uv tool install xxx.whl 全局安装,终端直接调用 CLI 小工具、脚本
生产-服务 专属 venv + systemd 进程管理、自愈、日志 Web 服务、后台任务
生产-容器 Docker 镜像 环境一致、隔离、可编排 微服务、云原生架构

六、核心原则

环境 做法 关键点
本地验证 uv run --with ./xxx.whl <cmd> 即用即弃,不污染环境
正式环境 先把 whl 装到专属 venv,再跑 entry point 固定环境、进程管理、日志收集

核心区别 :开发/验证时用 --with 临时创建环境;正式环境则先安装到独立位置,再用 systemd/Docker 管理进程生命周期。


两种类型对比总结

工具包(Library) 应用(Application)
有无 __main__.py
有无 [project.scripts]
安装方式 uv add greetlib uv tool install greetappuv add greetapp
主要使用方式 from greetlib import xxx 终端敲 greetapp
入口数 0 1 或多个

FAQ

1. __init__.py 能省略吗?

Python 3.3+ 允许没有 __init__.py 的隐式命名空间包(PEP 420),import 也能正常工作。但推荐加上,因为:

  • 可以在 __init__.py 里放公共导入、版本号、__all__
  • 控制包的 API 暴露范围
  • 避免意外把无关目录合并成命名空间包

2. __init__.py__main__.py 能不能只有一个?

__init__.py __main__.py 结果
import,不能 python -m
python -m,但 import 行为不确定(隐式命名空间包)
两者皆可

3. uv init --libuv init --app 有什么区别?

参数 生成的结构 自动添加
--lib src 布局 + src/包名/__init__.py py.typed 类型标记文件
--app 平级布局 + main.py 无额外配置

实际开发中,推荐无论 lib 还是 app 都用 src 布局--lib 的结构更规范),app 项目手动创建 __main__.py[project.scripts]

4. 什么情况用 uv run 什么情况用 uv add

场景 命令
临时跑一次脚本,不想污染环境 uv run python script.py
安装依赖到当前项目 uv add requests
全局安装一个 CLI 工具 uv tool install greetapp
在别的项目里引用一个本地包 uv add /path/to/mylib
相关推荐
念恒123062 小时前
Python(while循环)
数据结构·python·算法
星座5282 小时前
AI-Python机器学习与深度学习全栈实战:从机器学习、深度学习到自动化Agent在科学研究中的深度应用全揭秘
人工智能·python·机器学习
在坚持一下我可没意见2 小时前
Python 修仙修炼录 08:字典秘境,参悟键值玄机
开发语言·笔记·python·入门·字典
凌波粒2 小时前
深度学习入门(鱼书)第1章笔记——Python 基础
笔记·python·深度学习
WebGirl2 小时前
如何在VS code中添加SKill
前端
WL_Aurora2 小时前
Python 算法基础篇之查找算法(三):树表查找
python·算法
财经资讯数据_灵砚智能3 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月19日
大数据·人工智能·python·信息可视化·自然语言处理·灵砚智能
marsh02063 小时前
49 openclaw故障排查:系统异常时的诊断方法
服务器·前端·青少年编程·ai·php·技术美术
Maimai108083 小时前
前端如何落地 SSE:从实时评论到可复用的实时数据 Hook
前端·javascript·react.js·前端框架·web3·状态模式·webassembly