Fighting with venv in Python
Published: 2023-08-24 19:20:50

---
title: Fighting with venv in Python
published: true
date: 2023-08-24 06:09:15 UTC
tags: 
canonical_url: https://chrisparaiso.dev/fighting-with-venv-in-python
---

I had a brain fart today. I was developing a personal project in Python and I had some library issues that I was trying to wrap my head around. It turns out, I didn't even have my [virtual environment](https://docs.python.org/3/library/venv.html) running. I completely forgot.

So then I activated it.

```
source .venv/bin/activate

```

Then I thought to myself...

> I don't want to type that out every single damn time.

I'm lazy. I don't like to type unnecessary things. I switch projects mid-day on multiple occasions at work so there's a bit of a context switch to deal with. If I have to write automation scripts and aliases now to prevent me from typing even the smallest of words, I'll take the time to try to solve that.

## Context issues

So I did just that. I set aside some time to try to automate things.

I wanted a command I could execute (`venv`). This command would run a script that creates a virtual environment via `python3 -m venv .venv`. Then it would run `source .venv/bin/activate` to start the virtual environment.

Well, every time I ran this script, the directory would be created at the current working directory and the `source` line ran without error but the virtual environment did not start. The Python interpreter my environment was running was still global at `/usr/local/bin/python3`. So something is amiss!

After doing a bit of research it turns out that when you want to enter a virtual environment, the virtual environment modifies my shell's variables. An example of this would be modifying my shell's variables to point to the correct Python interpreter.

Also, when you run a Bash script, it executes in a different context/subshell. The file and directory changes stuck after the script ran, but the necessary variables I needed for my virtual environment were thrown away as soon as the script finished running.

## Solution

I removed the `source` line from my `venv.sh` script and just left the script to create the needed files and directories. I would then need to run that `source` command to enter the virtual environment.

Then I thought: Why don't I just string the commands together into one alias on my shell? Perfect.

```
# aliases.sh
alias venv='$HOME/src/dotfiles/bin/utils/venv.sh && \
    source .venv/bin/activate'

# ... other aliases below here

```

Running the `venv` alias would execute the `venv.sh` **then** run the `source` command in the context of the shell I am currently in.

```
#!/bin/bash
# venv.sh
# create venv if not exists
  if [-d ".venv"]; then
    echo "Found .venv. Activating..."
  else
    read -p ".venv does not exist. Would you like to \
         create a venv for this directory? (y/n) " response
    if ["$response" == "y"]; then
      echo "Creating .venv directory @ $PWD"
      python3 -m venv .venv
    fi
  fi

```

If `venv.sh` finds an existing `.venv` directory, it does nothing. If the script does not find the `.venv` directory it prompts the user asking if the script has permission to create it. I know I could probably do without the prompt and just have the script create it. I decided to leave it in for now.

The output of the command/script is shown below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692856783015/c4493fe1-e677-40e3-815e-ae72eb96168f.png)

I guess my issue was with Bash and not venv. Anyway, I think I have to be careful. I've been getting sidetracked and spending a lot of time configuring my environment. Off to building something!