Published 2021-04-09.
Last modified 2025-07-08.
Time to read: 10 minutes.
Python virtual environments are cheap to make and use – unless you are unfortunate enough to program in native Windows. I have adopted the habit of making a Python virtual environment (venv) for each significant Python project, plus a default venv for trivial Python work.
Python virtualization tools have evolved over the years.
Recently the uv
tool has become available,
and it solves the issues presented by previous generations of
tools so well that I rewrote this article to focus on uv
.
Why Virtualize Python?
It is better to use virtualized user- and project-specific Python instances, instead of working with a system-wide installation of Python. This allows you to install and upgrade Python packages without using supervisor privileges. Also, virtualized instances allows you to work on many different independent Python projects at the same time, without package version collisions.
Docker
is over-sold.
It adds unnecessary complexity to software projects.
Instead of virtualizing the entire software environment,
as docker
attempts to do,
virtualizing the Python programming environment as described in this article,
Ruby rbenv
,
or node.js nvm
are much easier and more productive approaches.
I think docker
has been pushed hard in the media because it is a gateway technology to
PaSS.
This is a trend that PaSS vendors like AWS and Azure want to encourage, but
customers are pushing back.
Uv
Uv
is a convenient and fast F/OSS Python package and virtualization manager.
First released only 17 months ago,
it has quickly become very popular.
Uv
is a single program with many subcommands that replaces other package and virtualization managers,
including pip
, pip-tools
, pipx
,
poetry
, pyenv
, twine
, venv
, virtualenv
, and others.
This article was originally written around venv
, but it has since been rewritten for uv
.
I switched from using venv
to uv
.
This saves me lots of aggravation.
The uv
GitHub repository is here.
The best way to install uv
is by typing:
$ curl -LsSf https://astral.sh/uv/install.sh | sh downloading uv 0.7.19 x86_64-unknown-linux-gnu no checksums to verify installing to /home/mslinn/.local/bin uv uvx everything's installed!
When installed this way, uv
can update itself to the latest version by typing:
$ uv self update info: Checking for updates... success: You're on the latest version of uv (v0.7.19)
The command syntax for uv
can be displayed by typing uv -h
,
uv --help
or uv help
:
$ uv -h An extremely fast Python package manager.
Usage: uv [OPTIONS] <COMMAND>
Commands: run Run a command or script init Create a new project add Add dependencies to the project remove Remove dependencies from the project version Read or update the project's version sync Update the project's environment lock Update the project's lockfile export Export the project's lockfile to an alternate format tree Display the project's dependency tree tool Run and install commands provided by Python packages python Manage Python versions and installations pip Manage Python packages with a pip-compatible interface venv Create a virtual environment build Build Python packages into source distributions and wheels publish Upload distributions to an index cache Manage uv's cache self Manage the uv executable help Display documentation for a command
Cache options: -n, --no-cache Avoid reading from or writing to the cache, instead using a temporary directory for the duration of the operation [env: UV_NO_CACHE=] --cache-dir <CACHE_DIR> Path to the cache directory [env: UV_CACHE_DIR=]
Python options: --managed-python Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=] --no-managed-python Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=] --no-python-downloads Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]
Global options: -q, --quiet... Use quiet output -v, --verbose... Use verbose output --color <COLOR_CHOICE> Control the use of color in output [possible values: auto, always, never] --native-tls Whether to load TLS certificates from the platform's native certificate store [env: UV_NATIVE_TLS=] --offline Disable network access [env: UV_OFFLINE=] --allow-insecure-host <ALLOW_INSECURE_HOST> Allow insecure connections to a host [env: UV_INSECURE_HOST=] --no-progress Hide all progress outputs [env: UV_NO_PROGRESS=] --directory <DIRECTORY> Change to the given directory prior to running the command --project <PROJECT> Run the command within the given project directory [env: UV_PROJECT=] --config-file <CONFIG_FILE> The path to a `uv.toml` file to use for configuration [env: UV_CONFIG_FILE=] --no-config Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=] -h, --help Display the concise help for this command -V, --version Display the uv version
Use `uv help` for more details.
What is uvx
?
Usage Example
Following along the uv
usage example
we can see that uv
has a subcommand called init
.
$ uv init example Initialized project `example` at `/home/mslinn/example`
$ cd example/
$ ls -alF total 8 drwxr-xr-x 1 mslinn mslinn 4096 Jul 8 11:00 ./ drwxr-xr-x 1 mslinn mslinn 4096 Jul 8 10:41 ../ drwxr-xr-x 1 mslinn mslinn 4096 Jul 8 10:41 .git/ -rw-r--r-- 1 mslinn mslinn 109 Jul 8 10:41 .gitignore -rw-r--r-- 1 mslinn mslinn 5 Jul 8 10:41 .python-version drwxr-xr-x 1 mslinn mslinn 4096 Jul 8 10:43 .venv/ -rw-r--r-- 1 mslinn mslinn 0 Jul 8 10:41 README.md -rw-r--r-- 1 mslinn mslinn 85 Jul 8 10:41 main.py -rw-r--r-- 1 mslinn mslinn 174 Jul 8 10:41 pyproject.toml -rw-r--r-- 1 mslinn mslinn 6028 Jul 8 10:41 uv.lock
One of the things that the uv init
subcommand does is create an empty new Git project,
just as if you had typed git init
.
As usual, the new Git project has no remote yet, and no commits.
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true
Uv
nails down the default Python version for the new project by creating a file called
.python-version
.
If you delete this file, the program will probably continue to work, but using the default version of Python
instead of the version that is known to work.
$ cat .python-version 3.13
Uv
also creates a
pyproject.toml
file containing properties for the new project.
You should edit this file to suit.
$ cat pyproject.toml [project] name = "example" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.13" dependencies = []
A very modest starting point for a Python program is created:
cat main.py def main(): print("Hello from example!")
if __name__ == "__main__": main()
Continuing with the example, I installed a Python dependency called
ruff
into the new Python project.
$ uv add ruff warning: `VIRTUAL_ENV=/home/mslinn/venv/default` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead Using CPython 3.13.3 interpreter at: /usr/bin/python3.13 Creating virtual environment at: .venv Resolved 2 packages in 231ms Prepared 1 package in 1.26s Installed 1 package in 27ms + ruff==0.12.2
I had neglected to deactivate my default virtual environment, which had been created by venv
, beforehand.
Uv
notified me that it handled that issue gracefully.
I deactivated the old virtual environment so the warning message will no longer appear each time uv
is run:
$ deactivate
Continuing with the example, we can run ruff
:
$ uv run ruff check All checks passed!
Looking inside the newly created .venv
directory, we see similarities to
virtual environments made with the venv
module:
$ tree .venv .venv ├── CACHEDIR.TAG ├── bin │ ├── activate │ ├── activate.bat │ ├── activate.csh │ ├── activate.fish │ ├── activate.nu │ ├── activate.ps1 │ ├── activate_this.py │ ├── deactivate.bat │ ├── pydoc.bat │ ├── python -> /usr/bin/python3.13 │ ├── python3 -> python │ ├── python3.13 -> python │ └── ruff ├── lib │ └── python3.13 │ └── site-packages │ ├── _virtualenv.pth │ ├── _virtualenv.py │ ├── ruff │ │ ├── __init__.py │ │ └── __main__.py │ └── ruff-0.12.2.dist-info │ ├── INSTALLER │ ├── METADATA │ ├── RECORD │ ├── REQUESTED │ ├── WHEEL │ └── licenses │ └── LICENSE ├── lib64 -> lib └── pyvenv.cfg
9 directories, 25 files
Locking is the process of resolving your project’s dependencies into a lockfile.
Lockfiles are called uv.lock
, and contain specifications for all dependencies, including
transitive dependencies.
Continuing with the example, we can update the project lockfile.
$ uv lock Resolved 2 packages in 1ms
Notice that the uv
lockfile is more complex than equivalent lockfiles for most other package managers.
version = 1 revision = 2 requires-python = ">=3.13"
[[package]] name = "example" version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "ruff" }, ]
[package.metadata] requires-dist = [{ name = "ruff", specifier = ">=0.12.2" }]
[[package]] name = "ruff" version = "0.12.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ]
Syncing
is the process of installing a subset of packages from the lockfile into the project environment.
A subdirectory tree whose root is called .venv
will be created if not already present.
Continuing with the example, explicitly update the project environment. While the project environment is automatically synced, it may also be explicitly synced:
$ uv sync Resolved 2 packages in 1ms Audited 1 package in 0.01ms
Up to this point, a local Git repository has been created, but there are no remote copies. If the GitHub CLI is installed, we can create a private GitHub repository, named after the current directory, and push the project to GitHub with the following incancation:
$ git add -A
$ git commit -m "Initial commit" [master (root-commit) ee73be2] Initial commit 6 files changed, 65 insertions(+) create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 README.md create mode 100644 main.py create mode 100644 pyproject.toml create mode 100644 uv.lock
$ gh repo create --private --source=. --remote=origin --push ✓ Created repository mslinn/example on GitHub https://github.com/mslinn/example ✓ Added remote git@github.com:mslinn/example.git Enumerating objects: 8, done. Counting objects: 100% (8/8), done. Delta compression using up to 12 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (8/8), 2.90 KiB | 990.00 KiB/s, done. Total 8 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To github.com:mslinn/example.git * [new branch] HEAD -> master branch 'master' set up to track 'origin/master'. ✓ Pushed commits to git@github.com:mslinn/example.git
uv python Subcommand
The help message for the uv python
subcommand is:
$ uv python Manage Python versions and installations
Usage: uv python [OPTIONS] <COMMAND>
Commands: list List the available Python installations install Download and install Python versions upgrade Upgrade installed Python versions to the latest supported patch release (requires the `--preview` flag) find Search for a Python installation pin Pin to a specific Python version dir Show the uv Python installation directory uninstall Uninstall Python versions
Cache options: -n, --no-cache Avoid reading from or writing to the cache, instead using a temporary directory for the duration of the operation [env: UV_NO_CACHE=] --cache-dir <CACHE_DIR> Path to the cache directory [env: UV_CACHE_DIR=]
Python options: --managed-python Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=] --no-managed-python Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=] --no-python-downloads Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]
Global options: -q, --quiet... Use quiet output -v, --verbose... Use verbose output --color <COLOR_CHOICE> Control the use of color in output [possible values: auto, always, never] --native-tls Whether to load TLS certificates from the platform's native certificate store [env: UV_NATIVE_TLS=] --offline Disable network access [env: UV_OFFLINE=] --allow-insecure-host <ALLOW_INSECURE_HOST> Allow insecure connections to a host [env: UV_INSECURE_HOST=] --no-progress Hide all progress outputs [env: UV_NO_PROGRESS=] --directory <DIRECTORY> Change to the given directory prior to running the command --project <PROJECT> Run the command within the given project directory [env: UV_PROJECT=] --config-file <CONFIG_FILE> The path to a `uv.toml` file to use for configuration [env: UV_CONFIG_FILE=] --no-config Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=] -h, --help Display the concise help for this command
Use `uv help python` for more details.
Display the Python executable path used by uv
.
For me, this path did not exist.
$ uv python dir /home/mslinn/.local/share/uv/python
Display the Python executable path that uv
uses to run Python programs:
$ cd $work/python/example
$ source ~/venv/default/bin/activate
(default) $ uv python find /home/mslinn/venv/default/bin/python3
(default) $ deactivate
$ uv python find /mnt/f/work/python/example/.venv/bin/python3
The above demonstrates that the uv find
subcommand gives priority to an activated venv
over a .venv
in the current directory.
We can display all available and installed versions of Python.
The following shows one installed version of Python (/usr/bin/python3.13
),
linked to an alias (/usr/bin/python3
).
$ uv python list cpython-3.14.0b3-linux-x86_64-gnu <download available> cpython-3.14.0b3+freethreaded-linux-x86_64-gnu <download available> cpython-3.13.5-linux-x86_64-gnu <download available> cpython-3.13.5+freethreaded-linux-x86_64-gnu <download available> cpython-3.13.3-linux-x86_64-gnu /usr/bin/python3.13 cpython-3.13.3-linux-x86_64-gnu /usr/bin/python3 -> python3.13 cpython-3.12.11-linux-x86_64-gnu <download available> cpython-3.11.13-linux-x86_64-gnu <download available> cpython-3.10.18-linux-x86_64-gnu <download available> cpython-3.9.23-linux-x86_64-gnu <download available> cpython-3.8.20-linux-x86_64-gnu <download available> pypy-3.11.11-linux-x86_64-gnu <download available> pypy-3.10.16-linux-x86_64-gnu <download available> pypy-3.9.19-linux-x86_64-gnu <download available> pypy-3.8.16-linux-x86_64-gnu <download available> graalpy-3.11.0-linux-x86_64-gnu <download available> graalpy-3.10.0-linux-x86_64-gnu <download available> graalpy-3.8.5-linux-x86_64-gnu <download available>
Manually Creating a Venv
The uv venv
subcommand creates a venv
.
The following example creates the venv
in $work/.venv/
:
$ cd $work
$ uv venv Using CPython 3.13.3 interpreter at: /usr/bin/python3 Creating virtual environment at: .venv Activate with: source .venv/bin/activate
uv run Subcommand
The uv run
help message is:
$ uv run -h Run a command or script
Usage: uv run [OPTIONS] [COMMAND]
Options: --extra <EXTRA> Include optional dependencies from the specified extra name --all-extras Include all optional dependencies --no-extra <NO_EXTRA> Exclude the specified optional dependencies, if `--all-extras` is supplied --no-dev Disable the development dependency group --group <GROUP> Include dependencies from the specified dependency group --no-group <NO_GROUP> Disable the specified dependency group --no-default-groups Ignore the default dependency groups --only-group <ONLY_GROUP> Only include dependencies from the specified dependency group --all-groups Include dependencies from all dependency groups -m, --module Run a Python module --only-dev Only include the development dependency group --no-editable Install any editable dependencies, including the project and any workspace members, as non-editable [env: UV_NO_EDITABLE=] --exact Perform an exact sync, removing extraneous packages --env-file <ENV_FILE> Load environment variables from a `.env` file [env: UV_ENV_FILE=] --no-env-file Avoid reading environment variables from a `.env` file [env: UV_NO_ENV_FILE=] --with <WITH> Run with the given packages installed --with-editable <WITH_EDITABLE> Run with the given packages installed in editable mode --with-requirements <WITH_REQUIREMENTS> Run with all packages listed in the given `requirements.txt` files --isolated Run the command in an isolated virtual environment --active Prefer the active virtual environment over the project's virtual environment --no-sync Avoid syncing the virtual environment [env: UV_NO_SYNC=] --locked Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=] --frozen Run without updating the `uv.lock` file [env: UV_FROZEN=] -s, --script Run the given path as a Python script --gui-script Run the given path as a Python GUI script --all-packages Run the command with all workspace members installed --package <PACKAGE> Run the command in a specific package in the workspace --no-project Avoid discovering the project or workspace
Index options: --index <INDEX> The URLs to use when resolving dependencies, in addition to the default index [env: UV_INDEX=] --default-index <DEFAULT_INDEX> The URL of the default package index (by default: <https://pypi.org/simple>) [env: UV_DEFAULT_INDEX=] -i, --index-url <INDEX_URL> (Deprecated: use `--default-index` instead) The URL of the Python package index (by default: <https://pypi.org/simple>) [env: UV_INDEX_URL=] --extra-index-url <EXTRA_INDEX_URL> (Deprecated: use `--index` instead) Extra URLs of package indexes to use, in addition to `--index-url` [env: UV_EXTRA_INDEX_URL=] -f, --find-links <FIND_LINKS> Locations to search for candidate distributions, in addition to those found in the registry indexes [env: UV_FIND_LINKS=] --no-index Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via `--find-links` --index-strategy <INDEX_STRATEGY> The strategy to use when resolving against multiple index URLs [env: UV_INDEX_STRATEGY=] [possible values: first-index, unsafe-first-match, unsafe-best-match] --keyring-provider <KEYRING_PROVIDER> Attempt to use `keyring` for authentication for index URLs [env: UV_KEYRING_PROVIDER=] [possible values: disabled, subprocess]
Resolver options: -U, --upgrade Allow package upgrades, ignoring pinned versions in any existing output file. Implies `--refresh` -P, --upgrade-package <UPGRADE_PACKAGE> Allow upgrades for a specific package, ignoring pinned versions in any existing output file. Implies `--refresh-package` --resolution <RESOLUTION> The strategy to use when selecting between the different compatible versions for a given package requirement [env: UV_RESOLUTION=] [possible values: highest, lowest, lowest-direct] --prerelease <PRERELEASE> The strategy to use when considering pre-release versions [env: UV_PRERELEASE=] [possible values: disallow, allow, if-necessary, explicit, if-necessary-or-explicit] --fork-strategy <FORK_STRATEGY> The strategy to use when selecting multiple versions of a given package across Python versions and platforms [env: UV_FORK_STRATEGY=] [possible values: fewest, requires-python] --exclude-newer <EXCLUDE_NEWER> Limit candidate packages to those that were uploaded prior to the given date [env: UV_EXCLUDE_NEWER=] --no-sources Ignore the `tool.uv.sources` table when resolving dependencies. Used to lock against the standards-compliant, publishable package metadata, as opposed to using any workspace, Git, URL, or local path sources
Installer options: --reinstall Reinstall all packages, regardless of whether they're already installed. Implies `--refresh` --reinstall-package <REINSTALL_PACKAGE> Reinstall a specific package, regardless of whether it's already installed. Implies `--refresh-package` --link-mode <LINK_MODE> The method to use when installing packages from the global cache [env: UV_LINK_MODE=] [possible values: clone, copy, hardlink, symlink] --compile-bytecode Compile Python files to bytecode after installation [env: UV_COMPILE_BYTECODE=]
Build options: -C, --config-setting <CONFIG_SETTING> Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs --no-build-isolation Disable isolation when building source distributions [env: UV_NO_BUILD_ISOLATION=] --no-build-isolation-package <NO_BUILD_ISOLATION_PACKAGE> Disable isolation when building source distributions for a specific package --no-build Don't build source distributions [env: UV_NO_BUILD=] --no-build-package <NO_BUILD_PACKAGE> Don't build source distributions for a specific package [env: UV_NO_BUILD_PACKAGE=] --no-binary Don't install pre-built wheels [env: UV_NO_BINARY=] --no-binary-package <NO_BINARY_PACKAGE> Don't install pre-built wheels for a specific package [env: UV_NO_BINARY_PACKAGE=]
Cache options: -n, --no-cache Avoid reading from or writing to the cache, instead using a temporary directory for the duration of the operation [env: UV_NO_CACHE=] --cache-dir <CACHE_DIR> Path to the cache directory [env: UV_CACHE_DIR=] --refresh Refresh all cached data --refresh-package <REFRESH_PACKAGE> Refresh cached data for a specific package
Python options: -p, --python <PYTHON> The Python interpreter to use for the run environment. [env: UV_PYTHON=] --managed-python Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=] --no-managed-python Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=] --no-python-downloads Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]
Global options: -q, --quiet... Use quiet output -v, --verbose... Use verbose output --color <COLOR_CHOICE> Control the use of color in output [possible values: auto, always, never] --native-tls Whether to load TLS certificates from the platform's native certificate store [env: UV_NATIVE_TLS=] --offline Disable network access [env: UV_OFFLINE=] --allow-insecure-host <ALLOW_INSECURE_HOST> Allow insecure connections to a host [env: UV_INSECURE_HOST=] --no-progress Hide all progress outputs [env: UV_NO_PROGRESS=] --directory <DIRECTORY> Change to the given directory prior to running the command --project <PROJECT> Run the command within the given project directory [env: UV_PROJECT=] --config-file <CONFIG_FILE> The path to a `uv.toml` file to use for configuration [env: UV_CONFIG_FILE=] --no-config Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=] -h, --help Display the concise help for this command
Use `uv help run` for more details.
Buried in the documentation is the important fact that the uv find
subcommand
resolves the venv very differently than the uv run
command.
Whereas uv find
gives precedence to a currently active venv
,
the uv run
subcommand gives precedence to the closest .venv
directory,
moving towards the directory root.
Here is a short Python program that displays the Python excutable path.
You can edit main.py
shown above so it looks like the following:
import sys
def main(): print("The current Python intepreter is " + sys.executable)
if __name__ == "__main__": main()
Now lets discover where Python is running from. That pesky warning message appears again:
$ uv run main.py warning: `VIRTUAL_ENV=/home/mslinn/venv/default` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead The current Python intepreter is /mnt/f/work/python/example/.venv/bin/python3
You can suppress the pesky warning with the uv run --no-active
option.
$ uv run --no-active main.py The current Python intepreter is /mnt/f/work/python/example/.venv/bin/python3
You could define an alias to always specify the --no-active
option:
alias uvrun='uv run --no-active'
Use the alias this way:
$ source ~/.bash_aliases
$ uvrun main.py The current Python intepreter is /mnt/f/work/python/example/.venv/bin/python3
Drop-in Pip Replacement
Uv
provides a
drop-in replacement for PIP.
No tears will be shed for the demise of PIP.
Migrating From venv to uv
Migrating python projects to uv.
Automatic Virtual Environment Activation and Deactivation
The built-in venv
module requires the user to manually activate
and deactivate
the appropriate virtual environment for each Python project or command.
That is operationally problematic and has implementation issues.
Here is an example of how to activate
a virtual environment previously created by uv
,
run a Python program, and deactivate
the virtual environment:
$ cd example
$ source .venv/bin/activate
(my_project) $ python main.py ...Output...
(my_project) $ deactivate $
Instead, the uv run
subcommand automatically activate
s and deactivate
s
the associated .venv
virtual environment for each project.
Automatically activate
the virtual environment before running the script and deactivate
it afterwards:
$ cd example
$ uv run main.py Hello from example!
Note that virtual environments made by other programs can be used by uv
,
so long as they are PEP 405 compliant.
When running a command that mutates an environment such as
uv pip sync
or uv pip install
,
uv
will search for a virtual environment in the following order:
-
An activated virtual environment based on the
VIRTUAL_ENV
environment variable. -
An activated Conda environment based on the
CONDA_PREFIX
environment variable. -
A virtual environment at
.venv
in the current directory, or in the nearest parent directory. -
If no virtual environment is found,
uv
will prompt the user to create one in the current directory viauv venv
.
See Discovery of Python environments for more information.
Default Virtual Environment
If you keep your Python projects in a directory tree, then placing a virtual environment in a subdirectory of the tree root will make it the default virtual environment for all subdirectories. In the following tree structure, the default Python virtual environment is highlighted.
$ cd $work
$ tree -dL 1 . ├── .venv ├── KnobKraft-orm ├── dl │ └─── .venv ├── example │ └─── .venv └── mp4ToText └─── .venv
Old Information
This remainder of this artcile describes what needed to be done before uv
was available.
I kept it because it provides background and motivation for the rest of this article.
If you are not interested in historical information, you can stop reading this article now.
Python’s Awkward Venv Virtualization Module
Venv
is an awkward tool to create isolated virtual Python environments.
It has been included with Python since Python v3.3,
which was released 12 years ago.
PEP 405 specifies Python’s
venv
virtualization module.
The two main problems I have with venv
are:
- A virtual environment must be manually activated before running a program contained within it.
-
The
PATH
environment variable often gets messed up when a virtual environment is activated. This can be extremely frustrating.
Deprecated Virtualization Modules
Python 3.6 was released 8 years ago.
It deprecated the other virtualization modules,
pyenv
and
virtualenv
.
Instead, use venv
, as described in this article.
Extra Installation Steps for Ubuntu
Venv
was included with Python on Ubuntu until Ubuntu 23.04
It virtualizes all the common Python executables.
Debian changed pip
’s behavior
as a result of
PEP 668 – Marking Python base environments as “externally managed”.
This affects Ubuntu because it is downstream.
Starting with Ubuntu 23.04, you need to install venv
by typing:
$ yes | sudo apt install python3.xx-venv
... where xx
is the minor version number of Python that is installed.
For Python 3.12, provided with Ubuntu 24.04 (Noble Numbat), the following incantation is required:
$ yes | sudo apt install python3.12-venv
For Python 3.11, provided with Ubuntu 23.10 (Mantic Minotaur), the following incantation is required:
$ yes | sudo apt install python3.11-venv
Some software projects use meta-packages to specify version-agnostic dependencies. Perhaps Python on Ubuntu will do so in the future.
In order to virtualize pip
, venv
needs to invoke ensurepip
,
which is not installed by default on Ubuntu.
On Ubuntu systems, the ensurepip
command is provided by a package called python3-pip
.
$ yes | sudo apt install python3-pip
You could install both of the above packages together, of course:
$ yes | sudo apt install python3.12-venv python3-pip
Manually Creating a VEnv
The following demonstrates how to create a new virtual python environment in the ~/venv/default/
directory.
Intermediate directories, such as venv
in this example, will be created as required.
$ python3 -m venv ~/venv/default
At this point, the virtual environment just contained executable images for Python.
$ ls ~/venv/default/** /home/mslinn/venv/default/lib64@ /home/mslinn/venv/default/pyvenv.cfg /home/mslinn/venv/default/bin: Activate.ps1 activate activate.csh activate.fish pip* pip3* pip3.10* python@ python3@ python3.10@ /home/mslinn/venv/default/include: /home/mslinn/venv/default/lib: python3.10/
Upgrading Python
Re-installing the venv
at a later date will update the version of Python in the venv
.
You will also need to install the appropriate python3-venv
package when upgrading Python.
Each time you (re)install a virtual environment, all pip
packages are removed.
To prevent the loss of your installed pip
packages,
use pip freeze
before upgrading Ubuntu,
so the pip packages are memorialized in requirements.txt
.
After upgrading Python, run pip install
to re-install the pip
packages.
The following incantation runs pip freeze
on every directory under ~/venv
,
and creates a file called requirements.txt
in each venv
directory:
$ find ~/venv -maxdepth 1 -mindepth 1 -type d -print0 |
while IFS= read -r -d '' DIR; do
source "$DIR/bin/activate"
pip freeze > "$DIR/requirements.txt"
done
The above incantation should be performed for each of your Python venvs before you upgrade Ubuntu, because sometimes Python venvs do not work after an upgrade. The next step should fix Python venvs that broke during an Ubuntu upgrade.
Here is an example showing the commands that must be typed to upgrade Python from v3.11 to v3.12, which you will have to do when upgrading from Ubuntu 23.10 to Ubuntu 24.04. Scroll the code window to see all the commands:
$ yes | sudo apt install python3.12-venv Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: python3.12-venv 0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded. Need to get 5676 B of archives. After this operation, 28.7 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 python3.12-venv amd64 3.12.3-1 [5676 B] Fetched 5676 B in 0s (31.1 kB/s) Selecting previously unselected package python3.12-venv. (Reading database ... 444385 files and directories currently installed.) Preparing to unpack .../python3.12-venv_3.12.3-1_amd64.deb ... Unpacking python3.12-venv (3.12.3-1) ... Setting up python3.12-venv (3.12.3-1) ... Scanning processes...
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
$ find ~/venv -maxdepth 1 -type d -print0 | while IFS= read -r -d '' DIR; do python3 -m venv "$DIR" source "$DIR/bin/activate" pip install -r "$DIR/requirements.txt" done
VEnvs are Nearly Free
The cost of a venv is virtually free for all OSes except native Windows. This is because on all OSes except native Windows, the executable images are linked by default, so they do not require much storage space.
The ls
command below shows that the python
program in the default
venv
is linked to /usr/bin/python3.10
.
$ ls -go ~/venv/default/bin/python lrwxrwxrwx 1 18 Apr 9 06:01 /home/mslinn/venv/default/bin/python -> python3*
Create a VEnv for Every Python Project
My projects are stored under the directory pointed to by $work
.
My standard procedure when making a Python project called $work/blah
is to also create a venv for it at within the project, at $work/blah/.venv/
.
I add an entry to .gitignore
that merely consists of a line that says .venv/
.
A bash alias could be defined called blah
that makes the project directory current and activates the venv:
alias blah="cd $work/blah; source ./venv/bin/activate"
Now you could type blah
at a shell prompt,
and you would be working on that project.
Boom!
Deactivate a VEnv
Stop using venvs with deactivate
.
Notice that the prompt changes.
(aw) $ deactivate $
Directory-Locked Python Virtualization
After setting up a Python virtual environment,
a quick examination of the pip
script
shows that it is hard-coded to the directory that it was made for:
$ head -n 1 ~/venv/aw/bin/pip #!/home/mslinn/venv/aw/bin/python
For virtualized environments, such as Docker, this means that a Python virtual environment created without Docker can only be used within a Docker image if the path to it is the same from within the Docker image as when it was created.
Poetry and Python Virtual Environments
Python venvs are a good way to isolate Python programs from each other, so their dependencies do not clash.
The two best-known package managers for Python are
PIP
and Poetry.
PIP
is bundled with Python, while Poetry needs to be explicitly installed.
Python venvs use links to provide virtualized Python commands.
Inside each venv
, you will find links to programs like python
, pip
and library dependencies for every project that installs dependencies while the venv
is active.
Poetry can:
- Create a venv in
.venv
- Install specified library dependencies
- Run the program using the venv dependencies
- Publish the Python package.
Installing Poetry
If you are not careful, installing Poetry could be a
chicken-and-egg race condition.
You do not want Poetry to be a dependency of the venv
that it manages,
because it is designed to manage the libraries within the venv
.
Poetry has a custom installer that creates a dedicated virtual environment for itself, and operates independently from other Python-related mechanisms. This isolated environment prevents unintentional upgrades or removals of dependencies, allowing Poetry to manage its own dependencies properly.
While it is possible to install Poetry using PIP within a venv, it is better to install Poetry system-wide. The Setup section below discusses how to do that.
PIP dependencies are often specified in a file called requirements.txt
.
This file ensures that a Python project uses the correct versions of dependencies
by listing all the packages and their versions.
Poetry uses a file called poetry.lock
for the same purpose.
In addition to the names and versions of the dependencies, poetry.lock
also specifies the hashes of the dependant source files.
Poetry Help Messages
The top-level help message for Poetry is:
$ poetry --help Description: Lists commands.
Usage: list [options] [--] [<namespace>]
Arguments: namespace The namespace name
Options: -h, --help Display help for the given command. When no command is given display help for the list command. -q, --quiet Do not output any message. -V, --version Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. -n, --no-interaction Do not ask any interactive question. --no-plugins Disables plugins. --no-cache Disables Poetry source caches. -C, --directory=DIRECTORY The working directory for the Poetry command (defaults to the current working directory). -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug.
Help: The list command lists all commands:
poetry list
You can also display the commands for a specific namespace:
poetry list test
The Poetry commands are:
$ poetry list Poetry (version 1.7.1)
Usage: command [options] [arguments]
Options: -h, --help Display help for the given command. When no command is given display help for the list command. -q, --quiet Do not output any message. -V, --version Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. -n, --no-interaction Do not ask any interactive question. --no-plugins Disables plugins. --no-cache Disables Poetry source caches. -C, --directory=DIRECTORY The working directory for the Poetry command (defaults to the current working directory). -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug.
Available commands: about Shows information about Poetry. add Adds a new dependency to pyproject.toml. build Builds a package, as a tarball and a wheel by default. check Validates the content of the pyproject.toml file and its consistency with the poetry.lock file. config Manages configuration settings. export Exports the lock file to alternative formats. help Displays help for a command. init Creates a basic pyproject.toml file in the current directory. install Installs the project dependencies. list Lists commands. lock Locks the project dependencies. new Creates a new Python project at <path>. publish Publishes a package to a remote repository. remove Removes a package from the project dependencies. run Runs a command in the appropriate environment. search Searches for packages on remote repositories. shell Spawns a shell within the virtual environment. show Shows information about packages. update Update the dependencies as according to the pyproject.toml file. version Shows the version of the project or bumps it when a valid bump rule is provided.
cache cache clear Clears a Poetry cache by name. cache list List Poetry's caches.
debug debug info Shows debug information. debug resolve Debugs dependency resolution.
env env info Displays information about the current environment. env list Lists all virtualenvs associated with the current project. env remove Remove virtual environments associated with the project. env use Activates or creates a new virtualenv for the current project.
self self add Add additional packages to Poetry's runtime environment. self install Install locked packages (incl. addons) required by this Poetry installation. self lock Lock the Poetry installation's system requirements. self remove Remove additional packages from Poetry's runtime environment. self show Show packages from Poetry's runtime environment. self show plugins Shows information about the currently installed plugins. self update Updates Poetry to the latest version.
source source add Add source configuration for project. source remove Remove source configured for the project. source show Show information about sources configured for the project.
Detecting a Venv
Active virtual environments suppress Poetry’s behavior.
For example:
$ poetry shell Virtual environment already activated: /home/mslinn/venv/default
If you want to use Poetry on a project, deactivate any active virtual environment before attempting to work on the project.
$ deactivate
Here is a fragment of a script that detects if a venv is active, and disables it if so:
# Disable any activated virtual environment VENV="$( dirname "$( which virtualenv)" )" if [ -d "$VENV" ]; then source "$VENV/activate" && deactivate; fi
Setup
The optimal process for setting up Poetry for use in a project is:
-
Install Poetry, preferably system-wide.
I used
apt
to install thepoetry
package.
Shell$ yes | sudo apt install python3-poetry
-
Configure Poetry to manage the libraries within the
venv
. Thepoetry config
help message is shown below. - Use Poetry to install the library dependencies.
- Use Poetry to run the program using the dependencies in the venv, and/or to spawn a command-line subshell that provides access to the dependencies managed by Poetry.
The help information for the poetry config
command is:
$ poetry config --help Description: Manages configuration settings.
Usage: config [options] [--] [<key> [<value>...]]
Arguments: key Setting key. value Setting value.
Options: --list List configuration settings. --unset Unset configuration setting. --local Set/Get from the project's local configuration. -h, --help Display help for the given command. When no command is given display help for the list command. -q, --quiet Do not output any message. -V, --version Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. -n, --no-interaction Do not ask any interactive question. --no-plugins Disables plugins. --no-cache Disables Poetry source caches. -C, --directory=DIRECTORY The working directory for the Poetry command (defaults to the current working directory). -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug.
Help: This command allows you to edit the poetry config settings and repositories.
To add a repository:
poetry config repositories.foo https://bar.com/simple/
To remove a repository (repo is a short alias for repositories):
poetry config --unset repo.foo
Initializing the Poetry .venv
Imagine you have a Python project stored in $my_project
.
$ cd $my_project
poetry install
The poetry install
subcommand installs dependencies specified in poetry.lock
,
within the venv.
The help information for the poetry install
command is:
$ poetry install --help Description: Installs the project dependencies.
Usage: install [options]
Options: --without=WITHOUT The dependency groups to ignore. (multiple values allowed) --with=WITH The optional dependency groups to include. (multiple values allowed) --only=ONLY The only dependency groups to include. (multiple values allowed) --no-dev Do not install the development dependencies. (Deprecated) --sync Synchronize the environment with the locked packages and the specified groups. --no-root Do not install the root package (the current project). --no-directory Do not install any directory path dependencies; useful to install dependencies without source code, e.g. for caching of Docker layers) --dry-run Output the operations but do not execute anything (implicitly enables --verbose). --remove-untracked Removes packages not present in the lock file. (Deprecated) -E, --extras=EXTRAS Extra sets of dependencies to install. (multiple values allowed) --all-extras Install all extra dependencies. --only-root Exclude all dependencies. --compile Compile Python source files to bytecode. (This option has no effect if modern-installation is disabled because the old installer always compiles.) -h, --help Display help for the given command. When no command is given display help for the list command. -q, --quiet Do not output any message. -V, --version Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. -n, --no-interaction Do not ask any interactive question. --no-plugins Disables plugins. --no-cache Disables Poetry source caches. -C, --directory=DIRECTORY The working directory for the Poetry command (defaults to the current working directory). -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug.
Help: The install command reads the poetry.lock file from the current directory, processes it, and downloads and installs all the libraries and dependencies outlined in that file. If the file does not exist it will look for pyproject.toml and do the same.
poetry install
By default, the above command will also install the current project. To install only the dependencies and not including the current project, run the command with the --no-root option like below:
poetry install --no-root
Here is an example of using poetry install
.
$ poetry install --with local Creating virtualenv private-gpt in /mnt/f/work/my_project/.venv
Created Files
The first time that Poetry does something, e.g. when the poetry install
or
poetry shell
subcommands are run,
Poetry creates a file in the project directory called poetry.toml
.
As an example, if your Python project is stored in /mnt/
,
poetry.toml
will contain:
[virtualenvs] create = true in-project = true path = "/mnt/c/work/my_project/.venv"
A file called .venv/pyvenv.cfg
is also created, which looks like this:
home = /usr/bin implementation = CPython version_info = 3.11.6.final.0 virtualenv = 20.24.1+ds include-system-site-packages = false base-prefix = /usr base-exec-prefix = /usr base-executable = /usr/bin/python3 prompt = my_project-py3.11
poetry run
The poetry run
subcommand runs Python programs and scripts with the virtual environment managed by Poetry.
$ poetry run python my_program
If the first line of a script is the shebang for running Python, like this:
#!/usr/bin/env python3
... then we do not need to specify python
or python3
on the command line.
$ poetry run my_script_containg_shebang
poetry shell
You could spawn a subshell
that provides access to the dependencies managed by Poetry with the poetry shell
subcommand:
$ poetry shell Creating virtualenv my_project in /mnt/f/work/evelyn/my_project/.venv Spawning shell within /mnt/f/work/my_project/.venv . /mnt/f/work/my_project/.venv/bin/activate . /mnt/f/work/my_project/.venv/bin/activate
To deactivate the virtual environment, and exit this new shell,
type CTRL-D or exit
.
poetry show --tree
You can view all the dependencies for a Poetry project like this:
$ poetry show --tree black 22.12.0 The uncompromising code formatter. ├── click >=8.0.0 │ └── colorama * ├── mypy-extensions >=0.4.3 ├── pathspec >=0.9.0 └── platformdirs >=2 boto3 1.34.2 The AWS SDK for Python ├── botocore >=1.34.2,<1.35.0 │ ├── jmespath >=0.7.1,<2.0.0 │ ├── python-dateutil >=2.1,<3.0.0 │ │ └── six >=1.5 │ └── urllib3 >=1.25.4,<2.1 ├── jmespath >=0.7.1,<2.0.0 └── s3transfer >=0.9.0,<0.10.0 └── botocore >=1.33.2,<2.0a.0 ├── jmespath >=0.7.1,<2.0.0 ├── python-dateutil >=2.1,<3.0.0 │ └── six >=1.5 └── urllib3 >=1.25.4,<2.1 chromadb 0.4.20 Chroma. ├── bcrypt >=4.0.1 ├── chroma-hnswlib 0.7.3 │ └── numpy * ├── fastapi >=0.95.2 │ ├── anyio >=3.7.1,<4.0.0 │ │ ├── idna >=2.8 │ │ └── sniffio >=1.1 │ ├── email-validator >=2.0.0 │ │ ├── dnspython >=2.0.0 │ │ └── idna >=2.0.0 (circular dependency aborted here) │ ├── httpx >=0.23.0 │ │ ├── anyio * (circular dependency aborted here) │ │ ├── certifi * │ │ ├── h2 >=3,<5 │ │ │ ├── hpack >=4.0,<5 │ │ │ └── hyperframe >=6.0,<7 │ │ ├── httpcore ==1.* │ │ │ ├── certifi * (circular dependency aborted here) │ │ │ └── h11 >=0.13,<0.15 │ │ ├── idna * (circular dependency aborted here) │ │ └── sniffio * (circular dependency aborted here) │ ├── itsdangerous >=1.1.0 │ ├── jinja2 >=2.11.2 │ │ └── markupsafe >=2.0 │ ├── orjson >=3.2.1 │ ├── pydantic >=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0 │ │ ├── annotated-types >=0.4.0 │ │ ├── pydantic-core 2.14.5 │ │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ │ └── typing-extensions >=4.6.1 (circular dependency aborted here) │ ├── pydantic-extra-types >=2.0.0 │ │ └── pydantic >=2.0.3 (circular dependency aborted here) │ ├── pydantic-settings >=2.0.0 │ │ ├── pydantic >=2.3.0 (circular dependency aborted here) │ │ └── python-dotenv >=0.21.0 │ ├── python-multipart >=0.0.5 │ ├── pyyaml >=5.3.1 │ ├── starlette >=0.27.0,<0.28.0 │ │ └── anyio >=3.4.0,<5 (circular dependency aborted here) │ ├── typing-extensions >=4.5.0 (circular dependency aborted here) │ ├── ujson >=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0 │ └── uvicorn >=0.12.0 │ ├── click >=7.0 │ │ └── colorama * │ ├── colorama >=0.4 (circular dependency aborted here) │ ├── h11 >=0.8 (circular dependency aborted here) │ ├── httptools >=0.5.0 │ ├── python-dotenv >=0.13 (circular dependency aborted here) │ ├── pyyaml >=5.1 (circular dependency aborted here) │ ├── uvloop >=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1 │ ├── watchfiles >=0.13 │ │ └── anyio >=3.0.0 (circular dependency aborted here) │ └── websockets >=10.4 ├── grpcio >=1.58.0 ├── importlib-resources * ├── kubernetes >=28.1.0 │ ├── certifi >=14.05.14 │ ├── google-auth >=1.0.1 │ │ ├── cachetools >=2.0.0,<6.0 │ │ ├── pyasn1-modules >=0.2.1 │ │ │ └── pyasn1 >=0.4.6,<0.6.0 │ │ └── rsa >=3.1.4,<5 │ │ └── pyasn1 >=0.1.3 (circular dependency aborted here) │ ├── oauthlib >=3.2.2 │ ├── python-dateutil >=2.5.3 │ │ └── six >=1.5 │ ├── pyyaml >=5.4.1 │ ├── requests * │ │ ├── certifi >=2017.4.17 (circular dependency aborted here) │ │ ├── charset-normalizer >=2,<4 │ │ ├── idna >=2.5,<4 │ │ └── urllib3 >=1.21.1,<3 │ ├── requests-oauthlib * │ │ ├── oauthlib >=3.0.0 (circular dependency aborted here) │ │ └── requests >=2.0.0 (circular dependency aborted here) │ ├── six >=1.9.0 (circular dependency aborted here) │ ├── urllib3 >=1.24.2,<2.0 (circular dependency aborted here) │ └── websocket-client >=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0 ├── mmh3 >=4.0.1 ├── numpy >=1.22.5 ├── onnxruntime >=1.14.1 │ ├── coloredlogs * │ │ └── humanfriendly >=9.1 │ │ └── pyreadline3 * │ ├── flatbuffers * │ ├── numpy >=1.21.6 │ ├── packaging * │ ├── protobuf * │ └── sympy * │ └── mpmath >=0.19 ├── opentelemetry-api >=1.2.0 │ ├── deprecated >=1.2.6 │ │ └── wrapt >=1.10,<2 │ └── importlib-metadata >=6.0,<7.0 │ └── zipp >=0.5 ├── opentelemetry-exporter-otlp-proto-grpc >=1.2.0 │ ├── backoff >=1.10.0,<3.0.0 │ ├── deprecated >=1.2.6 │ │ └── wrapt >=1.10,<2 │ ├── googleapis-common-protos >=1.52,<2.0 │ │ └── protobuf >=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0 │ ├── grpcio >=1.0.0,<2.0.0 │ ├── opentelemetry-api >=1.15,<2.0 │ │ ├── deprecated >=1.2.6 (circular dependency aborted here) │ │ └── importlib-metadata >=6.0,<7.0 │ │ └── zipp >=0.5 │ ├── opentelemetry-exporter-otlp-proto-common 1.21.0 │ │ ├── backoff >=1.10.0,<3.0.0 (circular dependency aborted here) │ │ └── opentelemetry-proto 1.21.0 │ │ └── protobuf >=3.19,<5.0 (circular dependency aborted here) │ ├── opentelemetry-proto 1.21.0 (circular dependency aborted here) │ └── opentelemetry-sdk >=1.21.0,<1.22.0 │ ├── opentelemetry-api 1.21.0 (circular dependency aborted here) │ ├── opentelemetry-semantic-conventions 0.42b0 │ └── typing-extensions >=3.7.4 ├── opentelemetry-instrumentation-fastapi >=0.41b0 │ ├── opentelemetry-api >=1.12,<2.0 │ │ ├── deprecated >=1.2.6 │ │ │ └── wrapt >=1.10,<2 │ │ └── importlib-metadata >=6.0,<7.0 │ │ └── zipp >=0.5 │ ├── opentelemetry-instrumentation 0.42b0 │ │ ├── opentelemetry-api >=1.4,<2.0 (circular dependency aborted here) │ │ ├── setuptools >=16.0 │ │ └── wrapt >=1.0.0,<2.0.0 (circular dependency aborted here) │ ├── opentelemetry-instrumentation-asgi 0.42b0 │ │ ├── asgiref >=3.0,<4.0 │ │ ├── opentelemetry-api >=1.12,<2.0 (circular dependency aborted here) │ │ ├── opentelemetry-instrumentation 0.42b0 (circular dependency aborted here) │ │ ├── opentelemetry-semantic-conventions 0.42b0 │ │ └── opentelemetry-util-http 0.42b0 │ ├── opentelemetry-semantic-conventions 0.42b0 (circular dependency aborted here) │ └── opentelemetry-util-http 0.42b0 (circular dependency aborted here) ├── opentelemetry-sdk >=1.2.0 │ ├── opentelemetry-api 1.21.0 │ │ ├── deprecated >=1.2.6 │ │ │ └── wrapt >=1.10,<2 │ │ └── importlib-metadata >=6.0,<7.0 │ │ └── zipp >=0.5 │ ├── opentelemetry-semantic-conventions 0.42b0 │ └── typing-extensions >=3.7.4 ├── overrides >=7.3.1 ├── posthog >=2.4.0 │ ├── backoff >=1.10.0 │ ├── monotonic >=1.5 │ ├── python-dateutil >2.1 │ │ └── six >=1.5 │ ├── requests >=2.7,<3.0 │ │ ├── certifi >=2017.4.17 │ │ ├── charset-normalizer >=2,<4 │ │ ├── idna >=2.5,<4 │ │ └── urllib3 >=1.21.1,<3 │ └── six >=1.5 (circular dependency aborted here) ├── pulsar-client >=3.1.0 │ └── certifi * ├── pydantic >=1.9 │ ├── annotated-types >=0.4.0 │ ├── pydantic-core 2.14.5 │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ └── typing-extensions >=4.6.1 (circular dependency aborted here) ├── pypika >=0.48.9 ├── pyyaml >=6.0.0 ├── requests >=2.28 │ ├── certifi >=2017.4.17 │ ├── charset-normalizer >=2,<4 │ ├── idna >=2.5,<4 │ └── urllib3 >=1.21.1,<3 ├── tenacity >=8.2.3 ├── tokenizers >=0.13.2 │ └── huggingface-hub >=0.16.4,<1.0 │ ├── filelock * │ ├── fsspec >=2023.5.0 │ │ ├── aiohttp <4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1 │ │ │ ├── aiosignal >=1.1.2 │ │ │ │ └── frozenlist >=1.1.0 │ │ │ ├── attrs >=17.3.0 │ │ │ ├── frozenlist >=1.1.1 (circular dependency aborted here) │ │ │ ├── multidict >=4.5,<7.0 │ │ │ └── yarl >=1.0,<2.0 │ │ │ ├── idna >=2.0 │ │ │ └── multidict >=4.0 (circular dependency aborted here) │ │ └── requests * │ │ ├── certifi >=2017.4.17 │ │ ├── charset-normalizer >=2,<4 │ │ ├── idna >=2.5,<4 (circular dependency aborted here) │ │ └── urllib3 >=1.21.1,<3 │ ├── packaging >=20.9 │ ├── pyyaml >=5.1 │ ├── requests * (circular dependency aborted here) │ ├── tqdm >=4.42.1 │ │ └── colorama * │ └── typing-extensions >=3.7.4.3 ├── tqdm >=4.65.0 │ └── colorama * ├── typer >=0.9.0 │ ├── click >=7.1.1,<9.0.0 │ │ └── colorama * │ ├── colorama >=0.4.3,<0.5.0 (circular dependency aborted here) │ ├── rich >=10.11.0,<14.0.0 │ │ ├── markdown-it-py >=2.2.0 │ │ │ └── mdurl >=0.1,<1.0 │ │ └── pygments >=2.13.0,<3.0.0 │ ├── shellingham >=1.3.0,<2.0.0 │ └── typing-extensions >=3.7.4.3 ├── typing-extensions >=4.5.0 └── uvicorn >=0.18.3 ├── click >=7.0 │ └── colorama * ├── colorama >=0.4 (circular dependency aborted here) ├── h11 >=0.8 ├── httptools >=0.5.0 ├── python-dotenv >=0.13 ├── pyyaml >=5.1 ├── uvloop >=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1 ├── watchfiles >=0.13 │ └── anyio >=3.0.0 │ ├── idna >=2.8 │ └── sniffio >=1.1 └── websockets >=10.4 fastapi 0.103.2 FastAPI framework, high performance, easy to learn, fast to code, ready for production ├── anyio >=3.7.1,<4.0.0 │ ├── idna >=2.8 │ └── sniffio >=1.1 ├── email-validator >=2.0.0 │ ├── dnspython >=2.0.0 │ └── idna >=2.0.0 ├── httpx >=0.23.0 │ ├── anyio * │ │ ├── idna >=2.8 │ │ └── sniffio >=1.1 │ ├── certifi * │ ├── h2 >=3,<5 │ │ ├── hpack >=4.0,<5 │ │ └── hyperframe >=6.0,<7 │ ├── httpcore ==1.* │ │ ├── certifi * (circular dependency aborted here) │ │ └── h11 >=0.13,<0.15 │ ├── idna * (circular dependency aborted here) │ └── sniffio * (circular dependency aborted here) ├── itsdangerous >=1.1.0 ├── jinja2 >=2.11.2 │ └── markupsafe >=2.0 ├── orjson >=3.2.1 ├── pydantic >=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0 │ ├── annotated-types >=0.4.0 │ ├── pydantic-core 2.14.5 │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ └── typing-extensions >=4.6.1 (circular dependency aborted here) ├── pydantic-extra-types >=2.0.0 │ └── pydantic >=2.0.3 │ ├── annotated-types >=0.4.0 │ ├── pydantic-core 2.14.5 │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ └── typing-extensions >=4.6.1 (circular dependency aborted here) ├── pydantic-settings >=2.0.0 │ ├── pydantic >=2.3.0 │ │ ├── annotated-types >=0.4.0 │ │ ├── pydantic-core 2.14.5 │ │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ │ └── typing-extensions >=4.6.1 (circular dependency aborted here) │ └── python-dotenv >=0.21.0 ├── python-multipart >=0.0.5 ├── pyyaml >=5.3.1 ├── starlette >=0.27.0,<0.28.0 │ └── anyio >=3.4.0,<5 │ ├── idna >=2.8 │ └── sniffio >=1.1 ├── typing-extensions >=4.5.0 ├── ujson >=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0 └── uvicorn >=0.12.0 ├── click >=7.0 │ └── colorama * ├── colorama >=0.4 (circular dependency aborted here) ├── h11 >=0.8 ├── httptools >=0.5.0 ├── python-dotenv >=0.13 ├── pyyaml >=5.1 ├── uvloop >=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1 ├── watchfiles >=0.13 │ └── anyio >=3.0.0 │ ├── idna >=2.8 │ └── sniffio >=1.1 └── websockets >=10.4 injector 0.21.0 Injector - Python dependency injection framework, inspired by Guice llama-index 0.9.3 Interface between LLMs and your data ├── aiohttp >=3.8.6,<4.0.0 │ ├── aiosignal >=1.1.2 │ │ └── frozenlist >=1.1.0 │ ├── attrs >=17.3.0 │ ├── frozenlist >=1.1.1 (circular dependency aborted here) │ ├── multidict >=4.5,<7.0 │ └── yarl >=1.0,<2.0 │ ├── idna >=2.0 │ └── multidict >=4.0 (circular dependency aborted here) ├── aiostream >=0.5.2,<0.6.0 │ └── typing-extensions * ├── beautifulsoup4 >=4.12.2,<5.0.0 │ └── soupsieve >1.2 ├── dataclasses-json >=0.5.7,<0.6.0 │ ├── marshmallow >=3.18.0,<4.0.0 │ │ └── packaging >=17.0 │ └── typing-inspect >=0.4.0,<1 │ ├── mypy-extensions >=0.3.0 │ └── typing-extensions >=3.7.4 ├── deprecated >=1.2.9.3 │ └── wrapt >=1.10,<2 ├── fsspec >=2023.5.0 │ ├── aiohttp <4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1 │ │ ├── aiosignal >=1.1.2 │ │ │ └── frozenlist >=1.1.0 │ │ ├── attrs >=17.3.0 │ │ ├── frozenlist >=1.1.1 (circular dependency aborted here) │ │ ├── multidict >=4.5,<7.0 │ │ └── yarl >=1.0,<2.0 │ │ ├── idna >=2.0 │ │ └── multidict >=4.0 (circular dependency aborted here) │ └── requests * │ ├── certifi >=2017.4.17 │ ├── charset-normalizer >=2,<4 │ ├── idna >=2.5,<4 (circular dependency aborted here) │ └── urllib3 >=1.21.1,<3 ├── httpx * │ ├── anyio * │ │ ├── idna >=2.8 │ │ └── sniffio >=1.1 │ ├── certifi * │ ├── h2 >=3,<5 │ │ ├── hpack >=4.0,<5 │ │ └── hyperframe >=6.0,<7 │ ├── httpcore ==1.* │ │ ├── certifi * (circular dependency aborted here) │ │ └── h11 >=0.13,<0.15 │ ├── idna * (circular dependency aborted here) │ └── sniffio * (circular dependency aborted here) ├── nest-asyncio >=1.5.8,<2.0.0 ├── nltk >=3.8.1,<4.0.0 │ ├── click * │ │ └── colorama * │ ├── joblib * │ ├── regex >=2021.8.3 │ └── tqdm * │ └── colorama * (circular dependency aborted here) ├── numpy * ├── openai >=1.1.0 │ ├── anyio >=3.5.0,<5 │ │ ├── idna >=2.8 │ │ └── sniffio >=1.1 │ ├── distro >=1.7.0,<2 │ ├── httpx >=0.23.0,<1 │ │ ├── anyio * (circular dependency aborted here) │ │ ├── certifi * │ │ ├── h2 >=3,<5 │ │ │ ├── hpack >=4.0,<5 │ │ │ └── hyperframe >=6.0,<7 │ │ ├── httpcore ==1.* │ │ │ ├── certifi * (circular dependency aborted here) │ │ │ └── h11 >=0.13,<0.15 │ │ ├── idna * (circular dependency aborted here) │ │ └── sniffio * (circular dependency aborted here) │ ├── pydantic >=1.9.0,<3 │ │ ├── annotated-types >=0.4.0 │ │ ├── pydantic-core 2.14.5 │ │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ │ └── typing-extensions >=4.6.1 (circular dependency aborted here) │ ├── sniffio * (circular dependency aborted here) │ ├── tqdm >4 │ │ └── colorama * │ └── typing-extensions >=4.5,<5 (circular dependency aborted here) ├── optimum >=1.13.2,<2.0.0 │ ├── coloredlogs * │ │ └── humanfriendly >=9.1 │ │ └── pyreadline3 * │ ├── datasets * │ │ ├── aiohttp * │ │ │ ├── aiosignal >=1.1.2 │ │ │ │ └── frozenlist >=1.1.0 │ │ │ ├── attrs >=17.3.0 │ │ │ ├── frozenlist >=1.1.1 (circular dependency aborted here) │ │ │ ├── multidict >=4.5,<7.0 │ │ │ └── yarl >=1.0,<2.0 │ │ │ ├── idna >=2.0 │ │ │ └── multidict >=4.0 (circular dependency aborted here) │ │ ├── dill >=0.3.0,<0.3.8 │ │ ├── fsspec >=2021.11.1 │ │ │ ├── aiohttp <4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1 (circular dependency aborted here) │ │ │ └── requests * │ │ │ ├── certifi >=2017.4.17 │ │ │ ├── charset-normalizer >=2,<4 │ │ │ ├── idna >=2.5,<4 (circular dependency aborted here) │ │ │ └── urllib3 >=1.21.1,<3 │ │ ├── huggingface-hub >=0.14.0,<1.0.0 │ │ │ ├── filelock * │ │ │ ├── fsspec >=2023.5.0 (circular dependency aborted here) │ │ │ ├── packaging >=20.9 │ │ │ ├── pyyaml >=5.1 │ │ │ ├── requests * (circular dependency aborted here) │ │ │ ├── tqdm >=4.42.1 │ │ │ │ └── colorama * │ │ │ └── typing-extensions >=3.7.4.3 │ │ ├── multiprocess * │ │ │ └── dill >=0.3.7 (circular dependency aborted here) │ │ ├── numpy >=1.17 │ │ ├── packaging * (circular dependency aborted here) │ │ ├── pandas * │ │ │ ├── numpy >=1.23.2,<2 (circular dependency aborted here) │ │ │ ├── python-dateutil >=2.8.2 │ │ │ │ └── six >=1.5 │ │ │ ├── pytz >=2020.1 │ │ │ └── tzdata >=2022.1 │ │ ├── pyarrow >=8.0.0 │ │ │ └── numpy >=1.16.6 (circular dependency aborted here) │ │ ├── pyyaml >=5.1 (circular dependency aborted here) │ │ ├── requests >=2.19.0 (circular dependency aborted here) │ │ ├── tqdm >=4.62.1 (circular dependency aborted here) │ │ └── xxhash * │ ├── datasets >=1.2.1 (circular dependency aborted here) │ ├── evaluate * │ │ ├── datasets >=2.0.0 (circular dependency aborted here) │ │ ├── dill * (circular dependency aborted here) │ │ ├── fsspec >=2021.05.0 (circular dependency aborted here) │ │ ├── huggingface-hub >=0.7.0 (circular dependency aborted here) │ │ ├── multiprocess * (circular dependency aborted here) │ │ ├── numpy >=1.17 (circular dependency aborted here) │ │ ├── packaging * (circular dependency aborted here) │ │ ├── pandas * (circular dependency aborted here) │ │ ├── requests >=2.19.0 (circular dependency aborted here) │ │ ├── responses <0.19 │ │ │ ├── requests >=2.0,<3.0 (circular dependency aborted here) │ │ │ └── urllib3 >=1.25.10 (circular dependency aborted here) │ │ ├── tqdm >=4.62.1 (circular dependency aborted here) │ │ └── xxhash * (circular dependency aborted here) │ ├── huggingface-hub >=0.8.0 (circular dependency aborted here) │ ├── numpy * (circular dependency aborted here) │ ├── onnx * │ │ ├── numpy * (circular dependency aborted here) │ │ └── protobuf >=3.20.2 │ ├── onnxruntime >=1.11.0 │ │ ├── coloredlogs * (circular dependency aborted here) │ │ ├── flatbuffers * │ │ ├── numpy >=1.21.6 (circular dependency aborted here) │ │ ├── packaging * (circular dependency aborted here) │ │ ├── protobuf * (circular dependency aborted here) │ │ └── sympy * │ │ └── mpmath >=0.19 │ ├── packaging * (circular dependency aborted here) │ ├── protobuf >=3.20.1 (circular dependency aborted here) │ ├── sympy * (circular dependency aborted here) │ ├── torch >=1.9 │ │ ├── filelock * (circular dependency aborted here) │ │ ├── fsspec * (circular dependency aborted here) │ │ ├── jinja2 * │ │ │ └── markupsafe >=2.0 │ │ ├── networkx * │ │ ├── nvidia-cublas-cu12 12.1.3.1 │ │ ├── nvidia-cuda-cupti-cu12 12.1.105 │ │ ├── nvidia-cuda-nvrtc-cu12 12.1.105 │ │ ├── nvidia-cuda-runtime-cu12 12.1.105 │ │ ├── nvidia-cudnn-cu12 8.9.2.26 │ │ │ └── nvidia-cublas-cu12 * (circular dependency aborted here) │ │ ├── nvidia-cufft-cu12 11.0.2.54 │ │ ├── nvidia-curand-cu12 10.3.2.106 │ │ ├── nvidia-cusolver-cu12 11.4.5.107 │ │ │ ├── nvidia-cublas-cu12 * (circular dependency aborted here) │ │ │ ├── nvidia-cusparse-cu12 * │ │ │ │ └── nvidia-nvjitlink-cu12 * │ │ │ └── nvidia-nvjitlink-cu12 * (circular dependency aborted here) │ │ ├── nvidia-cusparse-cu12 12.1.0.106 (circular dependency aborted here) │ │ ├── nvidia-nccl-cu12 2.18.1 │ │ ├── nvidia-nvtx-cu12 12.1.105 │ │ ├── sympy * (circular dependency aborted here) │ │ ├── triton 2.1.0 │ │ │ └── filelock * (circular dependency aborted here) │ │ └── typing-extensions * (circular dependency aborted here) │ └── transformers >=4.26.0 │ ├── accelerate >=0.21.0 │ │ ├── huggingface-hub * (circular dependency aborted here) │ │ ├── numpy >=1.17 (circular dependency aborted here) │ │ ├── packaging >=20.0 (circular dependency aborted here) │ │ ├── psutil * │ │ ├── pyyaml * (circular dependency aborted here) │ │ ├── safetensors >=0.3.1 │ │ └── torch >=1.10.0 (circular dependency aborted here) │ ├── filelock * (circular dependency aborted here) │ ├── huggingface-hub >=0.19.3,<1.0 (circular dependency aborted here) │ ├── numpy >=1.17 (circular dependency aborted here) │ ├── packaging >=20.0 (circular dependency aborted here) │ ├── protobuf * (circular dependency aborted here) │ ├── pyyaml >=5.1 (circular dependency aborted here) │ ├── regex !=2019.12.17 │ ├── requests * (circular dependency aborted here) │ ├── safetensors >=0.3.1 (circular dependency aborted here) │ ├── sentencepiece >=0.1.91,<0.1.92 || >0.1.92 │ ├── tokenizers >=0.14,<0.19 │ │ └── huggingface-hub >=0.16.4,<1.0 (circular dependency aborted here) │ ├── torch >=1.10,<1.12.0 || >1.12.0 (circular dependency aborted here) │ └── tqdm >=4.27 (circular dependency aborted here) ├── pandas * │ ├── numpy >=1.23.2,<2 │ ├── python-dateutil >=2.8.2 │ │ └── six >=1.5 │ ├── pytz >=2020.1 │ └── tzdata >=2022.1 ├── sentencepiece >=0.1.99,<0.2.0 ├── sqlalchemy >=1.4.49 │ ├── greenlet !=0.4.17 │ └── typing-extensions >=4.2.0 ├── tenacity >=8.2.0,<9.0.0 ├── tiktoken >=0.3.3 │ ├── regex >=2022.1.18 │ └── requests >=2.26.0 │ ├── certifi >=2017.4.17 │ ├── charset-normalizer >=2,<4 │ ├── idna >=2.5,<4 │ └── urllib3 >=1.21.1,<3 ├── transformers >=4.34.0,<5.0.0 │ ├── accelerate >=0.21.0 │ │ ├── huggingface-hub * │ │ │ ├── filelock * │ │ │ ├── fsspec >=2023.5.0 │ │ │ │ ├── aiohttp <4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1 │ │ │ │ │ ├── aiosignal >=1.1.2 │ │ │ │ │ │ └── frozenlist >=1.1.0 │ │ │ │ │ ├── attrs >=17.3.0 │ │ │ │ │ ├── frozenlist >=1.1.1 (circular dependency aborted here) │ │ │ │ │ ├── multidict >=4.5,<7.0 │ │ │ │ │ └── yarl >=1.0,<2.0 │ │ │ │ │ ├── idna >=2.0 │ │ │ │ │ └── multidict >=4.0 (circular dependency aborted here) │ │ │ │ └── requests * │ │ │ │ ├── certifi >=2017.4.17 │ │ │ │ ├── charset-normalizer >=2,<4 │ │ │ │ ├── idna >=2.5,<4 (circular dependency aborted here) │ │ │ │ └── urllib3 >=1.21.1,<3 │ │ │ ├── packaging >=20.9 │ │ │ ├── pyyaml >=5.1 │ │ │ ├── requests * (circular dependency aborted here) │ │ │ ├── tqdm >=4.42.1 │ │ │ │ └── colorama * │ │ │ └── typing-extensions >=3.7.4.3 │ │ ├── numpy >=1.17 │ │ ├── packaging >=20.0 (circular dependency aborted here) │ │ ├── psutil * │ │ ├── pyyaml * (circular dependency aborted here) │ │ ├── safetensors >=0.3.1 │ │ └── torch >=1.10.0 │ │ ├── filelock * (circular dependency aborted here) │ │ ├── fsspec * (circular dependency aborted here) │ │ ├── jinja2 * │ │ │ └── markupsafe >=2.0 │ │ ├── networkx * │ │ ├── nvidia-cublas-cu12 12.1.3.1 │ │ ├── nvidia-cuda-cupti-cu12 12.1.105 │ │ ├── nvidia-cuda-nvrtc-cu12 12.1.105 │ │ ├── nvidia-cuda-runtime-cu12 12.1.105 │ │ ├── nvidia-cudnn-cu12 8.9.2.26 │ │ │ └── nvidia-cublas-cu12 * (circular dependency aborted here) │ │ ├── nvidia-cufft-cu12 11.0.2.54 │ │ ├── nvidia-curand-cu12 10.3.2.106 │ │ ├── nvidia-cusolver-cu12 11.4.5.107 │ │ │ ├── nvidia-cublas-cu12 * (circular dependency aborted here) │ │ │ ├── nvidia-cusparse-cu12 * │ │ │ │ └── nvidia-nvjitlink-cu12 * │ │ │ └── nvidia-nvjitlink-cu12 * (circular dependency aborted here) │ │ ├── nvidia-cusparse-cu12 12.1.0.106 (circular dependency aborted here) │ │ ├── nvidia-nccl-cu12 2.18.1 │ │ ├── nvidia-nvtx-cu12 12.1.105 │ │ ├── sympy * │ │ │ └── mpmath >=0.19 │ │ ├── triton 2.1.0 │ │ │ └── filelock * (circular dependency aborted here) │ │ └── typing-extensions * (circular dependency aborted here) │ ├── filelock * (circular dependency aborted here) │ ├── huggingface-hub >=0.19.3,<1.0 (circular dependency aborted here) │ ├── numpy >=1.17 (circular dependency aborted here) │ ├── packaging >=20.0 (circular dependency aborted here) │ ├── protobuf * │ ├── pyyaml >=5.1 (circular dependency aborted here) │ ├── regex !=2019.12.17 │ ├── requests * (circular dependency aborted here) │ ├── safetensors >=0.3.1 (circular dependency aborted here) │ ├── sentencepiece >=0.1.91,<0.1.92 || >0.1.92 │ ├── tokenizers >=0.14,<0.19 │ │ └── huggingface-hub >=0.16.4,<1.0 (circular dependency aborted here) │ ├── torch >=1.10,<1.12.0 || >1.12.0 (circular dependency aborted here) │ └── tqdm >=4.27 (circular dependency aborted here) ├── typing-extensions >=4.5.0 ├── typing-inspect >=0.8.0 │ ├── mypy-extensions >=0.3.0 │ └── typing-extensions >=3.7.4 └── urllib3 <2 mypy 1.7.1 Optional static typing for Python ├── mypy-extensions >=1.0.0 └── typing-extensions >=4.1.0 pre-commit 2.21.0 A framework for managing and maintaining multi-language pre-commit hooks. ├── cfgv >=2.0.0 ├── identify >=1.0.0 ├── nodeenv >=0.11.1 │ └── setuptools * ├── pyyaml >=5.1 └── virtualenv >=20.10.0 ├── distlib >=0.3.7,<1 ├── filelock >=3.12.2,<4 └── platformdirs >=3.9.1,<5 pypdf 3.17.2 A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files pytest 7.4.3 pytest: simple powerful testing with Python ├── colorama * ├── iniconfig * ├── packaging * └── pluggy >=0.12,<2.0 pytest-asyncio 0.21.1 Pytest support for asyncio └── pytest >=7.0.0 ├── colorama * ├── iniconfig * ├── packaging * └── pluggy >=0.12,<2.0 pytest-cov 3.0.0 Pytest plugin for measuring coverage. ├── coverage >=5.2.1 └── pytest >=4.6 ├── colorama * ├── iniconfig * ├── packaging * └── pluggy >=0.12,<2.0 python-multipart 0.0.6 A streaming multipart parser for Python pyyaml 6.0.1 YAML parser and emitter for Python qdrant-client 1.7.0 Client library for the Qdrant vector search engine ├── grpcio >=1.41.0 ├── grpcio-tools >=1.41.0 │ ├── grpcio >=1.60.0 │ ├── protobuf >=4.21.6,<5.0dev │ └── setuptools * ├── httpx >=0.14.0 │ ├── anyio * │ │ ├── idna >=2.8 │ │ └── sniffio >=1.1 │ ├── certifi * │ ├── h2 >=3,<5 │ │ ├── hpack >=4.0,<5 │ │ └── hyperframe >=6.0,<7 │ ├── httpcore ==1.* │ │ ├── certifi * (circular dependency aborted here) │ │ └── h11 >=0.13,<0.15 │ ├── idna * (circular dependency aborted here) │ └── sniffio * (circular dependency aborted here) ├── numpy >=1.21 ├── portalocker >=2.7.0,<3.0.0 │ └── pywin32 >=226 ├── pydantic >=1.10.8 │ ├── annotated-types >=0.4.0 │ ├── pydantic-core 2.14.5 │ │ └── typing-extensions >=4.6.0,<4.7.0 || >4.7.0 │ └── typing-extensions >=4.6.1 (circular dependency aborted here) └── urllib3 >=1.26.14,<2.0.0 ruff 0.1.8 An extremely fast Python linter and code formatter, written in Rust. types-pyyaml 6.0.12.12 Typing stubs for PyYAML watchdog 3.0.0 Filesystem events monitoring
poetry update
You can update all the dependencies for a Poetry project like this:
$ poetry update
For Further Reading
Python Best Practices for a New Project in 2021. This article is already becoming dated. YMMV.
Summary
- Demonstrated how to make an alias for working with Python virtual environments (venvs) that are coupled with Python projects.
- Deactivating the current venv was demonstrated using the
deactivate
command, provided with every venv. - Locked directories mean that Python virtual environments should normally only be created in the same environment they are intended to be used.