Installers ignore pre-releases by default, so users only get an alpha, beta, release candidate or dev build if they ask for it, with pip install --pre or an exact version. PyPI does not accept local versions with a plus label. Use pre-releases for public testing and local versions for private builds.
The version forms
The version specifiers spec defines the segments. Here are the ones library authors use.
| Form | Example | Meaning |
|---|---|---|
| Final release | 1.2.0 | A normal release |
| Developmental | 1.2.0.dev1 | Early build, such as a nightly |
| Alpha | 1.2.0a1 | Early test |
| Beta | 1.2.0b1 | Later test |
| Release candidate | 1.2.0rc1 | Candidate for final |
| Post release | 1.2.0.post1 | Non code correction after final |
| Local | 1.2.0+label | Private or downstream build |
How installers treat pre-releases
The specification says pre-releases of any kind, including developmental releases, are implicitly excluded from version specifiers unless one of three things holds: they are already installed, the user explicitly requests them, or the only available version satisfying the specifier is a pre-release.
The packaging guide gives the practical form: pre-releases are ignored by default when picking dependency versions, unless explicitly requested, for example with pip install pkg==1.1a3 or pip install --pre pkg.
So publishing 1.3.0rc1 does not push the release candidate onto people who depend on your library with a normal range. That is exactly why release candidates are a safe way to get feedback.
Local versions on PyPI
A local version identifier is a public version followed by a plus sign and a label, such as 1.2.1+fedora.4. The spec says local versions should not be used when publishing upstream projects to a public index, though they may identify private builds from source. It then states that PyPI, being intended for upstream projects, must not allow local version identifiers.
Local versions are meant for downstream redistributors who carry patches, and for build tools. The guide's own example is a version generated from Git data, which looks like a dev release with a plus suffix.
If your build tool computes versions from Git, make sure release builds happen from a clean tagged commit. Otherwise you may produce a version with a local label that PyPI will reject.
A pre-release workflow for a library
- Pick the next version and add a suffix: a1 for early, b1 when feature complete, rc1 for a candidate.
- Publish it to TestPyPI first, as in our TestPyPI guide.
- Publish it to PyPI, and tell testers the exact install command with
--pre. - Fix issues and increment the number, such as rc2. The spec says it is clearer to create a new pre-release than to make a post release of one.
- Release the final version.
Mind your own constraints
If your library depends on another project's pre-release, your users need to opt in too. Avoid that in published metadata, because the specifier rules mean installs may fail or need extra flags.
Security angle
Pre-releases are still public artifacts that anyone can pin. Treat them with the same review and signing process as finals. A rushed release candidate is a popular place for mistakes to land.
Safeguard's dependency scanning and SBOM generation record exact versions, including pre-releases. A free scan shows what a project resolved.
Quick check
Will a release candidate reach everyone who depends on my library?
No. Installers skip pre-releases unless the user asks for them or no other version satisfies the specifier.
Can I upload 1.0+mybuild to PyPI?
No. The specification says PyPI must not allow local version identifiers.
What is a dev release for?
Early builds such as nightlies, or packager builds from source control that should not clash with later project releases.
Sources
Last reviewed: 19 October 2026.