diff --git a/docs/virtual-environments.md b/docs/virtual-environments.md index d4db3a77c3..f4302bd20c 100644 --- a/docs/virtual-environments.md +++ b/docs/virtual-environments.md @@ -1,40 +1,26 @@ # Virtual Environments -When you work in Python projects you probably should use a **virtual environment** (or a similar mechanism) to isolate the packages you install for each project. +When working on Python projects, it's best practice to use a **virtual environment** (or a similar mechanism) to isolate the packages installed for each project. -/// info +> **Note** +> If you already know about virtual environments, how to create and use them, feel free to skip this section. 🤓 -If you already know about virtual environments, how to create them and use them, you might want to skip this section. 🤓 +> **Tip** +> A **virtual environment** is different from an **environment variable**. +> +> * An **environment variable** is a system variable used by programs. +> * A **virtual environment** is a directory containing specific files. -/// - -/// tip - -A **virtual environment** is different than an **environment variable**. - -An **environment variable** is a variable in the system that can be used by programs. - -A **virtual environment** is a directory with some files in it. - -/// - -/// info - -This page will teach you how to use **virtual environments** and how they work. - -If you are ready to adopt a **tool that manages everything** for you (including installing Python), try uv. - -/// +> **Note** +> This page explains how to use **virtual environments** and how they work. +> +> If you are ready to adopt a **tool that manages everything** for you (including installing Python), try uv. ## Create a Project First, create a directory for your project. -What I normally do is that I create a directory named `code` inside my home/user directory. - -And inside of that I create one directory per project. - -
+I typically create a `code` directory inside my home/user directory, and then create one directory per project inside it. ```console // Go to the home directory @@ -49,140 +35,93 @@ $ mkdir awesome-project $ cd awesome-project ``` -
- ## Create a Virtual Environment -When you start working on a Python project **for the first time**, create a virtual environment **inside your project**. +When starting a Python project **for the first time**, create a virtual environment **inside your project**. -/// tip +> **Tip** +> You only need to do this **once per project**, not every time you work. -You only need to do this **once per project**, not every time you work. +### Using `venv` -/// - -//// tab | `venv` - -To create a virtual environment, you can use the `venv` module that comes with Python. - -
+To create a virtual environment, you can use the `venv` module included with Python. ```console $ python -m venv .venv ``` -
- -/// details | What that command means +
+What that command means * `python`: use the program called `python` * `-m`: call a module as a script, we'll tell it which module next * `venv`: use the module called `venv` that normally comes installed with Python * `.venv`: create the virtual environment in the new directory `.venv` -/// +
-//// - -//// tab | `uv` +### Using `uv` If you have `uv` installed, you can use it to create a virtual environment. -
- ```console $ uv venv ``` -
- -/// tip - -By default, `uv` will create a virtual environment in a directory called `.venv`. - -But you could customize it passing an additional argument with the directory name. - -/// - -//// +> **Tip** +> By default, `uv` will create a virtual environment in a directory called `.venv`. +> +> You can customize this by passing an additional argument with the directory name. That command creates a new virtual environment in a directory called `.venv`. -/// details | `.venv` or other name +
+`.venv` or other name You could create the virtual environment in a different directory, but there's a convention of calling it `.venv`. -/// +
## Activate the Virtual Environment Activate the new virtual environment so that any Python command you run or package you install uses it. -/// tip - -Do this **every time** you start a **new terminal session** to work on the project. +> **Tip** +> Do this **every time** you start a **new terminal session** to work on the project. -/// - -//// tab | Linux, macOS - -
+### Linux, macOS ```console $ source .venv/bin/activate ``` -
- -//// - -//// tab | Windows PowerShell - -
+### Windows PowerShell ```console $ .venv\Scripts\Activate.ps1 ``` -
- -//// - -//// tab | Windows Bash +### Windows Bash Or if you use Bash for Windows (e.g. Git Bash): -
- ```console $ source .venv/Scripts/activate ``` -
- -//// - -/// tip - -Every time you install a **new package** in that environment, **activate** the environment again. - -This makes sure that if you use a **terminal (CLI) program** installed by that package, you use the one from your virtual environment and not any other that could be installed globally, probably with a different version than what you need. - -/// +> **Tip** +> Every time you install a **new package** in that environment, **activate** the environment again. +> +> This ensures that if you use a **terminal (CLI) program** installed by that package, you use the one from your virtual environment and not any other that could be installed globally, possibly with a different version. ## Check the Virtual Environment is Active Check that the virtual environment is active (the previous command worked). -/// tip - -This is **optional**, but it's a good way to **check** that everything is working as expected and you are using the virtual environment you intended. - -/// +> **Tip** +> This is **optional**, but it's a good way to **check** that everything is working as expected and you are using the intended virtual environment. -//// tab | Linux, macOS, Windows Bash - -
+### Linux, macOS, Windows Bash ```console $ which python @@ -190,15 +129,9 @@ $ which python /home/user/code/awesome-project/.venv/bin/python ``` -
- If it shows the `python` binary at `.venv/bin/python`, inside of your project (in this case `awesome-project`), then it worked. 🎉 -//// - -//// tab | Windows PowerShell - -
+### Windows PowerShell ```console $ Get-Command python @@ -206,67 +139,44 @@ $ Get-Command python C:\Users\user\code\awesome-project\.venv\Scripts\python ``` -
- If it shows the `python` binary at `.venv\Scripts\python`, inside of your project (in this case `awesome-project`), then it worked. 🎉 -//// - ## Upgrade `pip` -/// tip - -If you use `uv` you would use it to install things instead of `pip`, so you don't need to upgrade `pip`. 😎 - -/// +> **Tip** +> If you use `uv`, you would use it to install things instead of `pip`, so you don't need to upgrade `pip`. 😎 If you are using `pip` to install packages (it comes by default with Python), you should **upgrade** it to the latest version. Many exotic errors while installing a package are solved by just upgrading `pip` first. -/// tip - -You would normally do this **once**, right after you create the virtual environment. - -/// +> **Tip** +> You would normally do this **once**, right after you create the virtual environment. Make sure the virtual environment is active (with the command above) and then run: -
- ```console $ python -m pip install --upgrade pip ---> 100% ``` -
- ## Add `.gitignore` If you are using **Git** (you should), add a `.gitignore` file to exclude everything in your `.venv` from Git. -/// tip - -If you used `uv` to create the virtual environment, it already did this for you, you can skip this step. 😎 - -/// - -/// tip - -Do this **once**, right after you create the virtual environment. +> **Tip** +> If you used `uv` to create the virtual environment, it already did this for you, so you can skip this step. 😎 -/// - -
+> **Tip** +> Do this **once**, right after you create the virtual environment. ```console $ echo "*" > .venv/.gitignore ``` -
- -/// details | What that command means +
+What that command means * `echo "*"`: will "print" the text `*` in the terminal (the next part changes that a bit) * `>`: anything printed to the terminal by the command to the left of `>` should not be printed but instead written to the file that goes to the right of `>` @@ -280,33 +190,25 @@ That command will create a file `.gitignore` with the content: * ``` -/// +
## Install Packages After activating the environment, you can install packages in it. -/// tip - -Do this **once** when installing or upgrading the packages your project needs. - -If you need to upgrade a version or add a new package you would **do this again**. - -/// +> **Tip** +> Do this **once** when installing or upgrading the packages your project needs. +> +> If you need to upgrade a version or add a new package you would **do this again**. ### Install Packages Directly If you're in a hurry and don't want to use a file to declare your project's package requirements, you can install them directly. -/// tip - -It's a (very) good idea to put the packages and versions your program needs in a file (for example `requirements.txt` or `pyproject.toml`). - -/// +> **Tip** +> It's a (very) good idea to put the packages and versions your program needs in a file (for example `requirements.txt` or `pyproject.toml`). -//// tab | `pip` - -
+### Using `pip` ```console $ pip install typer @@ -314,58 +216,37 @@ $ pip install typer ---> 100% ``` -
- -//// - -//// tab | `uv` +### Using `uv` If you have `uv`: -
- ```console $ uv pip install typer ---> 100% ``` -
- -//// - ### Install from `requirements.txt` If you have a `requirements.txt`, you can now use it to install its packages. -//// tab | `pip` - -
+### Using `pip` ```console $ pip install -r requirements.txt ---> 100% ``` -
- -//// - -//// tab | `uv` +### Using `uv` If you have `uv`: -
- ```console $ uv pip install -r requirements.txt ---> 100% ``` -
- -//// - -/// details | `requirements.txt` +
+requirements.txt A `requirements.txt` with some packages could look like: @@ -374,22 +255,18 @@ typer==0.13.0 rich==13.7.1 ``` -/// +
## Run Your Program After you activated the virtual environment, you can run your program, and it will use the Python inside of your virtual environment with the packages you installed there. -
- ```console $ python main.py Hello World ``` -
- ## Configure Your Editor You would probably use an editor, make sure you configure it to use the same virtual environment you created (it will probably autodetect it) so that you can get autocompletion and inline errors. @@ -399,39 +276,27 @@ For example: * VS Code * PyCharm -/// tip - -You normally have to do this only **once**, when you create the virtual environment. - -/// +> **Tip** +> You normally have to do this only **once**, when you create the virtual environment. ## Deactivate the Virtual Environment Once you are done working on your project you can **deactivate** the virtual environment. -
- ```console $ deactivate ``` -
- This way, when you run `python` it won't try to run it from that virtual environment with the packages installed there. ## Ready to Work Now you're ready to start working on your project. - - -/// tip - -Do you want to understand what's all that above? - -Continue reading. 👇🤓 - -/// +> **Tip** +> Do you want to understand what's all that above? +> +> Continue reading. 👇🤓 ## Why Virtual Environments @@ -467,14 +332,10 @@ But now the problem is, if you install the packages globally (in the global envi If you want to run `philosophers-stone` you will need to first install `harry` version `1`, for example with: -
- ```console $ pip install "harry==1" ``` -
- And then you would end up with `harry` version `1` installed in your global Python environment. ```mermaid @@ -489,14 +350,10 @@ flowchart LR But then if you want to run `prisoner-of-azkaban`, you will need to uninstall `harry` version `1` and install `harry` version `3` (or just installing version `3` would automatically uninstall version `1`). -
- ```console $ pip install "harry==3" ``` -
- And then you would end up with `harry` version `3` installed in your global Python environment. And if you try to run `philosophers-stone` again, there's a chance it would **not work** because it needs `harry` version `1`. @@ -516,11 +373,8 @@ flowchart LR end ``` -/// tip - -It's very common in Python packages to try the best to **avoid breaking changes** in **new versions**, but it's better to be safe, and install newer versions intentionally and when you can run the tests to check everything is working correctly. - -/// +> **Tip** +> It's very common in Python packages to try the best to **avoid breaking changes** in **new versions**, but it's better to be safe, and install newer versions intentionally and when you can run the tests to check everything is working correctly. Now, imagine that with **many** other **packages** that all your **projects depend on**. That's very difficult to manage. And you would probably end up running some projects with some **incompatible versions** of the packages, and not knowing why something isn't working. @@ -534,16 +388,12 @@ Some of these directories are the ones in charge of having all the packages you When you run: -
- ```console // Don't run this now, it's just an example 🤓 $ pip install typer ---> 100% ``` -
- That will download a compressed file with the Typer code, normally from PyPI. It will also **download** files for other packages that Typer depends on. @@ -581,59 +431,38 @@ flowchart TB When you activate a virtual environment, for example with: -//// tab | Linux, macOS - -
+### Linux, macOS ```console $ source .venv/bin/activate ``` -
- -//// - -//// tab | Windows PowerShell - -
+### Windows PowerShell ```console $ .venv\Scripts\Activate.ps1 ``` -
- -//// - -//// tab | Windows Bash +### Windows Bash Or if you use Bash for Windows (e.g. Git Bash): -
- ```console $ source .venv/Scripts/activate ``` -
- -//// - That command will create or modify some [environment variables](environment-variables.md){.internal-link target=_blank} that will be available for the next commands. One of those variables is the `PATH` variable. -/// tip - -You can learn more about the `PATH` environment variable in the [Environment Variables](environment-variables.md#path-environment-variable){.internal-link target=_blank} section. - -/// +> **Tip** +> You can learn more about the `PATH` environment variable in the [Environment Variables](environment-variables.md#path-environment-variable){.internal-link target=_blank} section. Activating a virtual environment adds its path `.venv/bin` (on Linux and macOS) or `.venv\Scripts` (on Windows) to the `PATH` environment variable. Let's say that before activating the environment, the `PATH` variable looked like this: -//// tab | Linux, macOS +### Linux, macOS ```plaintext /usr/bin:/bin:/usr/sbin:/sbin @@ -646,9 +475,7 @@ That means that the system would look for programs in: * `/usr/sbin` * `/sbin` -//// - -//// tab | Windows +### Windows ```plaintext C:\Windows\System32 @@ -658,11 +485,9 @@ That means that the system would look for programs in: * `C:\Windows\System32` -//// - After activating the virtual environment, the `PATH` variable would look something like this: -//// tab | Linux, macOS +### Linux, macOS ```plaintext /home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin @@ -684,9 +509,7 @@ So, when you type `python` in the terminal, the system will find the Python prog and use that one. -//// - -//// tab | Windows +### Windows ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 @@ -708,8 +531,6 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python and use that one. -//// - An important detail is that it will put the virtual environment path at the **beginning** of the `PATH` variable. The system will find it **before** finding any other Python available. This way, when you run `python`, it will use the Python **from the virtual environment** instead of any other `python` (for example, a `python` from a global environment). Activating a virtual environment also changes a couple of other things, but this is one of the most important things it does. @@ -718,9 +539,7 @@ Activating a virtual environment also changes a couple of other things, but this When you check if a virtual environment is active, for example with: -//// tab | Linux, macOS, Windows Bash - -
+### Linux, macOS, Windows Bash ```console $ which python @@ -728,13 +547,7 @@ $ which python /home/user/code/awesome-project/.venv/bin/python ``` -
- -//// - -//// tab | Windows PowerShell - -
+### Windows PowerShell ```console $ Get-Command python @@ -742,10 +555,6 @@ $ Get-Command python C:\Users\user\code\awesome-project\.venv\Scripts\python ``` -
- -//// - That means that the `python` program that will be used is the one **in the virtual environment**. you use `which` in Linux and macOS and `Get-Command` in Windows PowerShell. @@ -756,15 +565,12 @@ The most important part is that when you call `python`, that is the exact "`pyth So, you can confirm if you are in the correct virtual environment. -/// tip - -It's easy to activate one virtual environment, get one Python, and then **go to another project**. - -And the second project **wouldn't work** because you are using the **incorrect Python**, from a virtual environment for another project. - -It's useful being able to check what `python` is being used. 🤓 - -/// +> **Tip** +> It's easy to activate one virtual environment, get one Python, and then **go to another project**. +> +> And the second project **wouldn't work** because you are using the **incorrect Python**, from a virtual environment for another project. +> +> It's useful being able to check what `python` is being used. 🤓 ## Why Deactivate a Virtual Environment @@ -774,18 +580,12 @@ And then you want to work on **another project** `prisoner-of-azkaban`. You go to that project: -
- ```console $ cd ~/code/prisoner-of-azkaban ``` -
- If you don't deactivate the virtual environment for `philosophers-stone`, when you run `python` in the terminal, it will try to use the Python from `philosophers-stone`. -
- ```console $ cd ~/code/prisoner-of-azkaban @@ -797,12 +597,8 @@ Traceback (most recent call last): import sirius ``` -
- But if you deactivate the virtual environment and activate the new one for `prisoner-of-askaban` then when you run `python` it will use the Python from the virtual environment in `prisoner-of-azkaban`. -
- ```console $ cd ~/code/prisoner-of-azkaban @@ -818,8 +614,6 @@ $ python main.py I solemnly swear 🐺 ``` -
- ## Alternatives This is a simple guide to get you started and teach you how everything works **underneath**.