In the previous article Creating the First pip Package for Young Developers from Scratch, we introduced how to publish a pip package using the most common method.
A year has passed, and this year we are doing something new and releasing it with uv!
What is uv
uv is a newly released tool that can be used for Python version management, virtual environment management, managing installed pip packages, project deployment, configuration synchronization, and more.
Of course, the most important reason is just one word — fast!
Installing uv first
If you already have Python, it’s very simple:
pip install uv
Done ![]()
Of course, you can also install it through other methods, see Installation | uv for details.
Creating a new uv project
Create a new folder, then create a virtual environment, then initialize a uv project:
uv venv -p 3.10 # specify the Python version for the project
uv init
The virtual environment is installed by default in the .venv folder in the execution path. Activate the virtual environment and you can use it directly:
source .venv/bin/activate # macOS
#.venv/python/activate.exe # Windows
For example:
❯ source .venv/bin/activate
❯ which python
/Users/ww/coding/ocr-cli/.venv/bin/python
At the same time, you will see a new pyproject.toml file in the current path, which records the relevant information of this uv project.
If you need to add some dependencies to this project, use:
uv add package_name
Next, develop your pip package within this virtual environment. This tutorial skips this step, assuming you have already developed and tested your package.
Building and publishing the pip package to PyPI with uv
The pyproject.toml file created earlier through uv init can replace the traditional setup.py. If you are not familiar with setup.py, please review Creating the First pip Package for Young Developers from Scratch.
Apart from some uv-specific features, the part for writing pip packages is basically the same. See Packaging Python Projects - Python Packaging User Guide for details.
For example, my pyproject.toml looks like this (simplified):
[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "deepseek-ocr-cliv2"
version = "0.1.3"
description = "OCR recognition command-line tool"
readme = "README.md"
requires-python = ">=3.10"
license = { file = "LICENSE" }
classifiers = [
"License :: Other/Proprietary License",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12"
]
dependencies = [
"requests>=2.32.5",
]
[project.urls]
Homepage = "https://github.com/whitewatercn/deepseek-ocr-cli"
Repository = "https://github.com/whitewatercn/deepseek-ocr-cli"
[project.scripts]
dsocr = "dsocr.main:main"
[tool.setuptools.package-dir]
dsocr = "dsocr_core/dsocr"
[tool.setuptools.packages.find]
where = ["dsocr_core"]
include = ["dsocr*"]
Next, you can build it. You do not need to install the wheel and twine pip packages; just use uv’s built-in functions:
uv build -o ./dist
# -o specifies the output directory
Note that you must add the parameter -o ./dist at the end; otherwise, it will build to the home directory, and the publish command won’t find the built files.
At this point, you will see two files under the /dist folder:
❯ ls dist
deepseek_ocr_cliv2-0.1.4-py3-none-any.whl
deepseek_ocr_cliv2-0.1.4.tar.gz
Then use uv’s built-in function to publish; the following will publish successfully!
❯ uv publish
Publishing 2 files to https://upload.pypi.org/legacy/
Enter username ('__token__' if using a token): __token__
Enter password:
Uploading deepseek_ocr_cliv2-0.1.4-py3-none-any.whl (5.2KiB)
Uploading deepseek_ocr_cliv2-0.1.4.tar.gz (4.2KiB)
At the time of writing, PyPI no longer allows publishing via account and password; you must publish using a token. See Creating the First pip Package for Young Developers from Scratch for how to get a token.
Celebration
Compared to publishing with twine, uv build and publish are much faster.
You can try modifying my source code whitewatercn/deepseek-ocr-cli and publish it yourself.
I originally wanted to write a project that uses Silicon Valley API keys to call the deepseekocr API, but after writing it, I found that many people had already published it, so the project is discontinued
