pypiserver
pypiserver is a minimal PyPI compatible server for pip or easy_install, designed to serve packages from local directories. It is built on the Bottle web framework and supports uploading wheels, bdists, eggs, and accompanying PGP-signatures via standard Python packaging tools like pip, setuptools, and twine, or simply by copying files. As of version 2.4.1, it is actively maintained with frequent releases, typically several per year, focusing on maintenance, dependency updates, and new features.
Common errors
-
pypi-server: command not found
cause The `pypi-server` executable script is not in your system's PATH after installation, or pip installed it in a location not typically on PATH (e.g., a virtual environment's bin/Scripts folder).fixEnsure your virtual environment is activated, or add the Python site-packages script directory to your system's PATH. You can often find the script by `find $(pip env path) -name pypi-server` or `python -m pypiserver run ...` as an alternative. -
ERROR: Could not find a version that satisfies the requirement <package_name>
cause The package you are trying to install is not present in the directories served by `pypiserver`, or there is a spelling mismatch (case sensitivity), or the client is not configured to look at your local PyPI.fixVerify the package is in the `pypiserver`'s package directory and that the name matches exactly (case-sensitive). Ensure your `pip` client is configured with `--index-url` pointing to your `pypiserver` and `--trusted-host` if using HTTP. Check `pypi-server` logs for 'package not found' entries. -
Server randomly hangs or becomes unresponsive during uploads/installs.
cause This can occur due to underlying WSGI server issues (e.g., `gevent` deadlocks), high load, or configuration mismatches. Older `bottle` versions were specifically used in v2.4.0 to mitigate large file upload issues.fixEnsure `pypiserver` is running with a stable WSGI server (e.g., `waitress` or `gunicorn` with appropriate workers). Check server logs for errors or stack traces. Consider enabling caching (`pip install pypiserver[cache]`) for many packages. Monitor system resources (CPU, RAM, file descriptors). -
500 Internal Server Error during package upload.
cause Typically a permissions issue on the package storage directory, preventing `pypiserver` from writing the uploaded files.fixEnsure the user account running the `pypi-server` process has write permissions to the designated package directory (e.g., `~/my_pypi_packages`). Check `pypi-server` logs for specific error details related to file operations. -
Installation errors due to PyPI redirects or misspellings when using a fallback PyPI mirror.
cause The main PyPI (pypi.org) performs 301 redirects for common misspellings (e.g., 'babel' to 'Babel'). When `pypiserver` with a fallback mirror receives a misspelled request, it may redirect to the mirror, which then 404s, leading to an installation failure as the correct spelling is not found.fixEnsure package names match their canonical PyPI spellings. Consider adding commonly misspelled packages manually to your local `pypiserver` index or configure your reverse proxy (if any) to handle common redirects. This is a known limitation when combining local indices with fallback to PyPI mirrors without sophisticated redirect handling.
Warnings
- breaking Python 3.7 support was removed in v2.4.0. Python 3.6 support was removed in v2.1.0. Ensure your Python environment meets the `>=3.10` requirement.
- gotcha The default hashing algorithm for package links switched to SHA256 in v2.0.0. This might affect clients or tools expecting MD5 hashes, though modern tooling generally supports SHA256.
- gotcha pypiserver does not implement the full PyPI API. Specifically, documentation uploads are accepted but not saved to disk. Also, advanced features like PEP 708 support are not yet implemented.
- gotcha When serving a local PyPI over HTTP (not HTTPS), `pip` will issue an 'untrusted' warning. You must explicitly add `--trusted-host` to your `pip install` commands or configure it permanently in `pip.conf` or environment variables.
- deprecated The `--root` option for specifying package directories is deprecated in favor of passing package directories as positional arguments directly to `pypi-server run`.
Install
-
pip install pypiserver -
pip install pypiserver[passlib,cache]
Imports
- app
from pypiserver import app
Quickstart
# 1. Install pypiserver (if not already done) # pip install pypiserver # 2. Create a directory to store your packages mkdir -p ~/my_pypi_packages # 3. Start the PyPI server in the background # This will serve packages from ~/my_pypi_packages on port 8080 pypi-server run -p 8080 ~/my_pypi_packages & # 4. (Optional) Create a dummy package to upload mkdir my_dummy_package echo 'from setuptools import setup, find_packages\nsetup(name="my-dummy-package", version="0.1.0", packages=find_packages())' > my_dummy_package/setup.py echo '__init__.py' > my_dummy_package/my_dummy_package/__init__.py pip install build twine python -m build --sdist --wheel my_dummy_package # 5. Upload a package using twine # Replace 'dist/*' with the path to your package files (e.g., .whl, .tar.gz) twine upload --repository-url http://localhost:8080 dist/* # 6. Install a package from your local PyPI server # For HTTP, you might need --trusted-host if pip complains pip install --index-url http://localhost:8080/simple/ --trusted-host localhost my-dummy-package # To stop the server later, find its process ID (e.g., `pgrep pypi-server`) and `kill <PID>`