Python venv? pip? what are these things?

Python venv? pip? what are these things?

As you get started with Python, there are a few concepts that definitely help maintain your system clean and your code isolated from other environments and potential issues.  On this post, we will look into two incredibly helpful modules - venv and pip!


venv

venv is a python module that allows the user to create a lightweight virtual environment for their python applications/scripts.  This is incredibly helpful and beneficial, as it allows the user to isolate the python application from the system executables and environment configurations.

venv is a module that is already included in python3, starting with version 3.3 and forward.  Here is a link to the official python doc - https://docs.python.org/3/library/venv.html.

Whenever I start a new script and/or a new app, the first thing that I setup is my virtual environment, and these instructions will guide you through that setup:

Step 1 - create a base folder for your app

mkdir myawesomeapp
cd myawesomeapp

Step 2 - setup a virtual environment for your new app

python3 -m venv ./env

Now that we have a folder for our app, and a virtual environment inside of it, we will proceed with activating and later on installing packages on our virtual environment.

Step 3 - activate your new virtual environment

This will activate the new virtual environment and isolates the package management, code execution and more to this new environment, and therefore it keeps the system folders clean and clear of any impact from this new environment.

source ./env/bin/activate

once activated, the prompt in your terminal will be prepended with the environment name, in this case it would look something like this:

 

pip

pip is a package manager for python that allows users to install packages from the Python Package Index (pypi.org).  Here is a link to the official python doc: https://docs.python.org/3/installing/index.html.

If you have been following the path above, you should now have a new folder for your app, as well as a new environment configured for your packages and python executable isolation.  Now, let's continue from the path above and install a sample package!  We will be installing the famous requests package, which is a super helpful HTTP library, and one of the most downloaded packages in pypi.

The command to do this is pip install requests.  Please be sure that you have your environment activated before running this command.

pip install requests
Collecting requests
  Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting idna<3,>=2.5
  Using cached idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting certifi>=2017.4.17
  Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
     |████████████████████████████████| 145 kB 7.5 MB/s 
Collecting chardet<5,>=3.0.2
  Using cached chardet-4.0.0-py2.py3-none-any.whl (178 kB)
Collecting urllib3<1.27,>=1.21.1
  Downloading urllib3-1.26.6-py2.py3-none-any.whl (138 kB)
     |████████████████████████████████| 138 kB 9.6 MB/s 
Installing collected packages: urllib3, idna, chardet, certifi, requests
Successfully installed certifi-2021.5.30 chardet-4.0.0 idna-2.10 requests-2.25.1 urllib3-1.26.6

Now let's have a little bit of fun with the requests library, shall we?

import requests


def main():
    base_url = "https://swapi.dev/api/"
    search_url = "people/?search="

    r = requests.get(f"{base_url}{search_url}vader")
    print(f"status: {r.status_code}")
    print(r.json())


if __name__ == "__main__":
    main()
starwars.py

On the example above, we defined a base_url for the Star Wars API, then appended a search_url for a person record and finally made a request to search for "vader".  Once the result is captured into a variable, in this case "r", we just print the status code and json payload from the response.  The result should be something like this:

python starwars.py
status: 200
{'count': 1, 'next': None, 'previous': None, 'results': [{'name': 'Darth Vader', 'height': '202', 'mass': '136', 'hair_color': 'none', 'skin_color': 'white', 'eye_color': 'yellow', 'birth_year': '41.9BBY', 'gender': 'male', 'homeworld': 'https://swapi.dev/api/planets/1/', 'films': ['https://swapi.dev/api/films/1/', 'https://swapi.dev/api/films/2/', 'https://swapi.dev/api/films/3/', 'https://swapi.dev/api/films/6/'], 'species': [], 'vehicles': [], 'starships': ['https://swapi.dev/api/starships/13/'], 'created': '2014-12-10T15:18:20.704000Z', 'edited': '2014-12-20T21:17:50.313000Z', 'url': 'https://swapi.dev/api/people/4/'}]}

and if we isolate just the json response, this is what we get:

{
    "count": 1, 
    "next": null, 
    "previous": null, 
    "results": [
        {
            "name": "Darth Vader", 
            "height": "202", 
            "mass": "136", 
            "hair_color": "none", 
            "skin_color": "white", 
            "eye_color": "yellow", 
            "birth_year": "41.9BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.dev/api/planets/1/", 
            "films": [
                "https://swapi.dev/api/films/1/", 
                "https://swapi.dev/api/films/2/", 
                "https://swapi.dev/api/films/3/", 
                "https://swapi.dev/api/films/6/"
            ], 
            "species": [], 
            "vehicles": [], 
            "starships": [
                "https://swapi.dev/api/starships/13/"
            ], 
            "created": "2014-12-10T15:18:20.704000Z", 
            "edited": "2014-12-20T21:17:50.313000Z", 
            "url": "https://swapi.dev/api/people/4/"
        }
    ]
}

Once you are done installing any necessary packages, and are ready to wrap things up, you can "freeze" the package list into a requirements file in order to keep a running list of the exact packages (and versions) that you used during development.  You can do this by executing the pip freeze command and sending the output to a requirements.txt file.  Here is what that looks like:

pip freeze > requirements.txt
cat requirements.txt
certifi==2021.5.30
chardet==4.0.0
idna==2.10
requests==2.25.1
urllib3==1.26.6

This practice ensures that anyone can easily replicate the environment in which the setup was performed.  In order to setup the new environment, all that a new user has to do is ask pip to install the packages AFTER the virtual environment is activated, such as:

pip install -r requirements.txt
Collecting certifi==2021.5.30
  Using cached certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
Collecting chardet==4.0.0
  Using cached chardet-4.0.0-py2.py3-none-any.whl (178 kB)
Collecting idna==2.10
  Using cached idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting requests==2.25.1
  Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting urllib3==1.26.6
  Using cached urllib3-1.26.6-py2.py3-none-any.whl (138 kB)
Installing collected packages: urllib3, idna, chardet, certifi, requests
Successfully installed certifi-2021.5.30 chardet-4.0.0 idna-2.10 requests-2.25.1 urllib3-1.26.6

I hope that helps you get started and understanding the pythonic way to handle environments and package management!

cheers!


the entire script can be found in the moshpit repo within my github account, directly linked here.

Featured image created by Chris Ried, downloaded from unsplash, licensed under the unsplash license.