{"id":5841,"date":"2021-04-15T20:40:38","date_gmt":"2021-04-15T20:40:38","guid":{"rendered":"https:\/\/blog.ssdnodes.com\/blog\/?p=5841"},"modified":"2025-05-18T19:47:05","modified_gmt":"2025-05-18T19:47:05","slug":"python-3-setup-using-venv","status":"publish","type":"post","link":"https:\/\/www.ssdnodes.com\/blog\/python-3-setup-using-venv\/","title":{"rendered":"Simplifying Python 3 setup using venv"},"content":{"rendered":"<h2>Dependency hell<\/h2>\n<p>Without virtual environments, working with Python is a nightmare! In case of Ubuntu, the base operating system comes with Python preinstalled, and you might think that that\\'s a nice thing. Except, that version of Python is old and pip is not even installed. So you install <code>pip<\/code> only to find out that it is detecting and trying to update Python programs that are part of the base operating system and are supposed to be managed by your operating system's package manager.<\/p>\n<\/p>\n<p>This same pattern of unavailability and conflicts gets worse over time as you start working on multiple Python projects. Dependencies of one might conflict with the other. You may require a specific version of <code>request<\/code> package for one project and a different version for another, and on and on. This frustration is well-depicted in this XKCD Comic:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/imgs.xkcd.com\/comics\/python_environment.png\" alt=\"Python Dependency Hell\" title=\"Python Dependency Hell\" \/><\/p>\n<p>This post tries to address all these problems, and then some more. Obviously, most of this is aimmed at Linux users, and is tested on a Ubuntu 20.04 LTS server, but the principles can be generalized for macOS and Windows 10 too.<\/p>\n<h2>Goals<\/h2>\n<p>The goal is to achieve the following with regards to our Python 3 environment:<\/p>\n<ul>\n<li>Isolating it from the broader Operating system.<\/li>\n<li>Making it easy to configure and backup<\/li>\n<li>Making it easily upgradable<\/li>\n<li>Using methods recommended by the Official Documentation<\/li>\n<\/ul>\n<p>We will be using <code>venv<\/code> module which is the recommended way to create virtual environments<\/p>\n<h2>Python venv to the rescue<\/h2>\n<p>In Python 3.6 the problem of managing multiple dependencies has received the cleanest resolution -- Virtual Environments or venv. In my opinion, this has rendered a lot of third party options like conda, pyenv, etc less relevant, if not completely redundant.<\/p>\n<p><code>venv<\/code> is an official Python module that is meant for running an isolated Python environment. This isolated environment can include Python interpreter, pip, and setuptools. All these dependencies are packaged into a user-specified directory.<\/p>\n<h2>Creating a virtual environment or venv<\/h2>\n<p>To get started, let\\'s install venv on our system first:<\/p>\n<pre><code>$ sudo apt install python3-venv<\/code><\/pre>\n<p>Let's create a virtual environment next. I will name this virtual environment, <code>my-venv<\/code> and it will be created in the user\\'s home directory for this specific case.<\/p>\n<pre><code>$ python3 -m venv $HOME\/my-venv<\/code><\/pre>\n<p>For Ubuntu 20.04, we had to use <code>python3<\/code> in the command instead of just <code>python<\/code> because <code>python<\/code> word is reserved for Python version 2. Same is true for macOS, but if you\\'ve installed <a href=\"https:\/\/www.python.org\/downloads\/\" title=\"Python on Windows\" target=\"_blank\" rel=\"noopener\">Python on Windows<\/a> then you can just use <code>python<\/code> to invoke Python 3 interpreter.<\/p>\n<h2>Activating and using a virtual environment or venv<\/h2>\n<p>To start using the virtual environment, we need to import a script located at <code>$HOME\/my-venv\/bin<\/code> into our SHELL environment. This script will be add the virtual environment\\'s directory to your shell\\'s PATH environment such that when <code>python<\/code> or <code>pip<\/code> or other packages are searched for the SHELL will search the virtual environment\\'s directory first search the <code>my-venv<\/code> directory to look for appropriate python program.<\/p>\n<p>Depending on your SHELL the script you need to invoke will be different. For <code>bash<\/code>, and <code>zsh<\/code> interpreters the script is named <code>activate<\/code>:<\/p>\n<pre><code>root@node-00:~# source ~\/my-venv\/bin\/activate\n(my-venv) root@node-00:~#<\/code><\/pre>\n<p>For <code>fish<\/code> shell the script is called <code>activate.fish<\/code> and there is a similar script for <code>tsch<\/code> in the same directory. For Windows 10, the scripts will have a <code>.bat<\/code> and <code>.ps1<\/code> extensions for command prompt and powershell respectively. Use the command <code>echo $SHELL<\/code> to know what shell your system is using.<\/p>\n<p>Notice in the above shell, once the <code>venv<\/code> is activated the prompt changed. It also has a copy of <code>pip<\/code> install by default. You can verify this and even update it:<\/p>\n<pre><code>$ pip --version\npip 20.0.2 from \/root\/my-venv\/lib\/python3.8\/site-packages\/pip (python 3.8)<\/code><\/pre>\n<p>To list all the packages installed, and to update them just do the following:<\/p>\n<pre><code>$ pip list\nPackage       Version\n------------- -------\npip           20.0.2\npkg-resources 0.0.0\nsetuptools    44.0.0\n\n$ pip install --upgrade pip pkg-resources setuptools\n$ pip list\nPackage       Version\n------------- -------\npip           21.0.1\npkg-resources 0.0.0\nsetuptools    56.0.0<\/code><\/pre>\n<p>This won\\'t update your system\\'s copy of <code>pip<\/code> or any other pip package you have installed system-wide. The version of Python being used is the same as the Python command used to create your virtual environment.<\/p>\n<p>You can install any number of <code>pip<\/code> packages inside this environment and use it for your Python projects. As long as the environment is active, the Python interpreter will prioritize these packages when your scripts call for a specific module, regardless of where you are in your filesystem. Once you are done working on the project, and want to switch gears simply type in <code>deactivate<\/code> and the virtual environment will be disabled:<\/p>\n<pre><code>(my-venv) root@node-00:~# deactivate\nroot@node-00:~#<\/code><\/pre>\n<p>Notice that the prompt is back to being normal. You can always reactivate the venv by running the <code>source<\/code> command along with the <code>activate<\/code> script. If your environment is broken simply remove the directory to get rid of it. Make sure that your Python project's file don't live in the same directory as the virtual environment.<\/p>\n<h2>Note on Updating Packages and Portability<\/h2>\n<p>Once you have installed necessary packages, it is always important to keep a snapshot of all the packages and their version numbers. This allows you to maintain and upgrade things gradually without the risk of things breaking down.<\/p>\n<pre><code>$ pip freeze &gt; requirements.txt<\/code><\/pre>\n<p>By convention the <code>requirements.txt<\/code> file is used to store all the packages. Here's a typical output:<\/p>\n<pre><code>click==7.1.2\ncycler==0.10.0\njoblib==1.0.1\nkiwisolver==1.3.1\nmatplotlib==3.4.1\nnltk==3.6.1\nnumpy==1.20.2\nPillow==8.2.0\npyparsing==2.4.7\npython-dateutil==2.8.1\nregex==2021.4.4\nsix==1.15.0\ntextblob==0.15.3\ntqdm==4.60.0<\/code><\/pre>\n<p>It also allows you to:<\/p>\n<ul>\n<li>Recreate the environment quickly and exactly, even if the underlying packages update in the future. Reinstall the same packages using the following command:\n<pre><code>$ pip install -r requirements.txt<\/code><\/pre>\n<\/li>\n<li>Keep track of the dependencies with your version control like git or GitHub.<\/li>\n<li>Reuse the file for other parts of your CI\/CD like when creating a Docker image for your file.<\/li>\n<\/ul>\n<p>That\\'s it for Python environments! Happy computing!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dependency hell Without virtual environments, working with Python is a nightmare! In case of Ubuntu, the base operating system comes with Python preinstalled, and you might think that that\\&#8217;s a nice thing. Except, that version of Python is old and pip is not even installed. So you install pip only to find out that it  &#8230;<\/p>\n","protected":false},"author":20,"featured_media":6075,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[18,30],"tags":[213,214],"class_list":["post-5841","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-tutorials","tag-python","tag-venv"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5841","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/comments?post=5841"}],"version-history":[{"count":2,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5841\/revisions"}],"predecessor-version":[{"id":13068,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5841\/revisions\/13068"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media\/6075"}],"wp:attachment":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media?parent=5841"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/categories?post=5841"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/tags?post=5841"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}