{"id":515,"date":"2026-04-25T01:22:33","date_gmt":"2026-04-25T01:22:33","guid":{"rendered":"https:\/\/beginnerprojects.com\/cms\/?p=515"},"modified":"2026-04-25T02:35:58","modified_gmt":"2026-04-25T02:35:58","slug":"python-virtual-environments-explained-for-beginners","status":"publish","type":"post","link":"https:\/\/beginnerprojects.com\/cms\/python-virtual-environments-explained-for-beginners\/","title":{"rendered":"Python Virtual Environments Explained for Beginners"},"content":{"rendered":"\n<p>I remember the first time my Python script suddenly broke because another project of mine installed a conflicting, outdated version of a library. It was a frustrating headache where my script stopped working for no obvious reason. That was the day I decided to stop sharing global Python installations and start using <strong>virtual environments<\/strong>.<\/p>\n\n\n\n<p>For anyone starting out who has heard the term &#8220;<strong>venv<\/strong>&#8221; and wants to know exactly why I bother setting one up, this is essentially how I handle my local development.<\/p>\n\n\n\n<p><a href=\"https:\/\/beginnerprojects.com\/cms\/how-to-install-vscodium-a-free-and-easy-to-use-code-editor\/\" data-type=\"post\" data-id=\"124\">Do you need a free code editor that doesn&#8217;t collect telemetry?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is a Virtual Environment?<\/h2>\n\n\n\n<p>Think of a virtual environment as a private room for a single project. By default, Python looks at the global &#8220;living room&#8221; where all my installed libraries live. When I activate a venv, I step into that private room where only the libraries I explicitly choose for this specific project are allowed. <br><br>This way, my custom python projects never accidentally conflict with the default python install which is used by <a href=\"https:\/\/beginnerprojects.com\/cms\/the-end-of-the-search-why-mx-linux-is-my-final-destination-part-ii\/\" data-type=\"post\" data-id=\"288\">my operating system which is MX Linux<\/a>. <strong>Every project I create gets its own isolated ecosystem.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Environment<\/h2>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"780\" height=\"256\" src=\"https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-environments-explained-for-beginners.webp\" alt=\"screenshot of the file manager showing the files needed to follow this python environment tutorial for beginners\" class=\"wp-image-528\" srcset=\"https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-environments-explained-for-beginners.webp 780w, https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-environments-explained-for-beginners-300x98.webp 300w, https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-environments-explained-for-beginners-768x252.webp 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><figcaption class=\"wp-element-caption\">My browser showing all the files needed for this project<\/figcaption><\/figure>\n\n\n\n<p>I always start by setting up a folder (directory) where my project will live. Then, I open the terminal and issue this command:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Windows:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>python -m venv venv<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>macOS and Linux:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>python3 -m venv venv<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>I always name my venv, &#8220;venv&#8221; because it is the standard convention across the Python world and it makes activating them faster. Plus, it saves me from having to remember a custom name every time I run a project.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Activation<\/h2>\n\n\n\n<p>Now that the folder exists, it sits there doing nothing until I tell my system to use it. This is the &#8220;activation&#8221; step. It sounds like magic, but what it actually does is simply modify my terminal&#8217;s PATH variable so that the python executable I type is pulled from the project folder, not the global installation.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Windows:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>venv\\Scripts\\activate<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>macOS and Linux:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>source venv\/bin\/activate<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>After that, I notice the (venv) appearing at the beginning of my command prompt. I always look for that little hint. It is my mental safety net reminding me, <em>&#8220;Yes, you&#8217;re in the private room.&#8221;<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Recipe Card (requirements.txt)<\/h2>\n\n\n\n<p>While I am inside my venv, I can install libraries I need for the project to run. The learner project on this page needs two libraries. Pillow and qrcode. To install them, I type:<br><code>pip install pillow<\/code><br><code>pip install qrcode<\/code><br>and watch the packages install inside my project folder.<\/p>\n\n\n\n<p>After that, I freeze my current state into a file called requirements.txt. I do this by running:<\/p>\n\n\n\n<pre class=\"wp-block-code has-palette-color-7-color has-palette-color-4-background-color has-text-color has-background has-link-color wp-elements-1eaf1a983cef6c2fe7793108015f8c0f\"><code>pip freeze &gt; requirements.txt<\/code><\/pre>\n\n\n\n<p>This file is just a plain text list of every library I have installed, pinned to exact versions. I find it to be an invaluable recipe card for my project&#8217;s dependencies. You can see it right here:<\/p>\n\n\n\n<p class=\"has-palette-color-11-background-color has-background\">pillow==12.2.0<br>qrcode==8.2<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deactivation and Deletion<\/h2>\n\n\n\n<p>When I am done working on my script for the day, I simply type <strong>deactivate<\/strong> to close the &#8220;private room&#8221; and return to the global living room. The (venv) tag disappears from my prompt.<\/p>\n\n\n\n<p>If I decide I never want to touch this project again, I simply delete the entire project folder. Because the libraries are completely isolated inside that folder, deleting it is effectively the same as uninstalling everything at once.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Something I Wish I Knew Sooner<\/h2>\n\n\n\n<p>Here is the biggest pitfall I ran into when I first started. Virtual environments are tied to my specific system architecture and local file paths.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><em><strong>If I move my project folder to a different computer, or if I restore my project folder from a backup, the venv folder becomes a useless relic.<\/strong> The internal paths are broken. I cannot just copy it over. <\/em><\/p>\n\n\n\n<p>In these cases, my process is simple: I delete the old venv, create a brand new one on the target machine, and then run: <br><code>pip install -r requirements.txt<\/code> <br>to rebuild my environment using that &#8220;recipe card&#8221; I made earlier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Quick Project to Get You Started<\/h2>\n\n\n\n<p>To show you how all of this works in practice, I have built a simple tool that you can use right now. It is a Command Line Interface (CLI) <strong>QR Code Generator<\/strong>.<\/p>\n\n\n\n<p>To get started, copy the code and save it as <strong>main.py<\/strong><br><em>Did you <a href=\"https:\/\/beginnerprojects.com\/cms\/critical-the-golden-rule-of-free-code\/\" data-type=\"post\" data-id=\"169\"><strong>read my WARNING<\/strong><\/a> to NEVER run code from the internet?<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code has-palette-color-11-background-color has-background\"><code>#!\/usr\/bin\/env python3\nimport qrcode\nimport sys\nfrom datetime import datetime\n\ndef generate_qr(data, filename=None, fill_color=\"black\", back_color=\"white\"):\n    if not filename:\n        timestamp = datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n        filename = f\"qr_code_{timestamp}.png\"\n\n    try:\n        qr = qrcode.QRCode(\n            version=1,\n            error_correction=qrcode.constants.ERROR_CORRECT_H,\n            box_size=10,\n            border=4,\n        )\n        qr.add_data(data)\n        qr.make(fit=True)\n\n        # Create the actual image\n        img = qr.make_image(fill_color=fill_color, back_color=back_color)\n        img.save(filename)\n        print(f\"Success! QR code saved as {filename}\")\n\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n\nif __name__ == \"__main__\":\n    print(\"--- My Simple QR Code Generator ---\")\n\n    text = input(\"Enter a URL or text to encode: \")\n\n    if text.strip():\n        # Ask if the user wants custom colors (optional)\n        custom = input(\"Change colors? (yes\/no) &#091;no]: \").strip().lower()\n\n        if custom == \"yes\":\n            fill = input(\"Fill color (e.g., 'red', '#FF0000'): \")\n            back = input(\"Background color (e.g., 'white', '#FFFFFF'): \")\n            generate_qr(text, fill_color=fill, back_color=back)\n        else:\n            generate_qr(text)\n    else:\n        print(\"Nothing entered. Goodbye!\")\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Instructions<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Set up a virtual environment (Linux): <br><code>python3 -m venv venv<\/code><\/li>\n\n\n\n<li>Activate the environment: <br><code>source venv\/bin\/activate<\/code><\/li>\n\n\n\n<li>Install the dependency: <br><code>pip install qrcode<\/code><br><code>pip install pillow<\/code><\/li>\n\n\n\n<li>Make the script (<strong>main.py<\/strong> which you just created) executable by typing: <br><code>chmod +x main.py<\/code><br>&#8211; <em>Note that &#8220;main.py&#8221; is the file name that contains the code I have published above)<\/em><\/li>\n\n\n\n<li>Now, i can run my new tool by typing: <code>python .\/main.py<\/code><\/li>\n<\/ol>\n\n\n\n<p><strong>What the code does:<\/strong><br>When I run the script, it asks me to type a URL. Once I do and press enter, it generates a PNG file containing a scannable QR code and saves it to my project folder.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"410\" height=\"410\" src=\"https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-virtual-environments-qr-code.png\" alt=\"qr code generated by a python virtual environments script\" class=\"wp-image-518\" srcset=\"https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-virtual-environments-qr-code.png 410w, https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-virtual-environments-qr-code-300x300.png 300w, https:\/\/beginnerprojects.com\/cms\/wp-content\/uploads\/2026\/04\/python-virtual-environments-qr-code-150x150.png 150w\" sizes=\"auto, (max-width: 410px) 100vw, 410px\" \/><figcaption class=\"wp-element-caption\">Screenshot of a QR code I generated<\/figcaption><\/figure>\n\n\n\n<p>I hope this explains why I rely on virtual environments and helps you to get started with virtual python environments.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\" \/>\n\n\n\n<h2 class=\"wp-block-heading\">Supplemental information<\/h2>\n\n\n\n<p>After I posted this blog post, I fired up Hermes Agent and gave it this command:<\/p>\n\n\n\n<p class=\"has-palette-color-7-color has-palette-color-4-background-color has-text-color has-background has-link-color wp-elements-d05733358d23a16400dfdf43159849d5\">pleae read this blog post: https:\/\/beginnerprojects.com\/cms\/python-virtual-environments-explained-for-beginners\/ and verify that it is accurate. that all instructions are correct.<\/p>\n\n\n\n<p><strong>Here is the output:<\/strong><\/p>\n\n\n\n<p>\u250a \ud83c\udf10 preparing browser_navigate\u2026<br>\u250a \ud83c\udf10 navigate beginnerprojects.com 1.4s<br>\u250a \ud83d\udcf8 preparing browser_snapshot\u2026<br>\u250a \ud83d\udcf8 snapshot full 0.3s<br>\u250a \ud83d\udcf8 preparing browser_snapshot\u2026<br>\u250a \ud83d\udcf8 snapshot full 0.3s<br>\u250a \ud83d\udcf8 preparing browser_snapshot\u2026<br>\u250a \ud83d\udcf8 snapshot full 0.2s<\/p>\n\n\n\n<p>\u256d\u2500 \u2695 Hermes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e<br>I have reviewed the blog post, and I can confirm that it is technically accurate and the instructions are correct.<\/p>\n\n\n\n<p>Here is the detailed verification of the steps provided:<br><br>*   Creation: The commands python -m venv venv (Windows) and python3 -m venv venv (macOS\/Linux) are the industry standard for creating isolated environments.<br>*   Activation: <br>    *   venv\\Scripts\\activate is correct for Windows (CMD).<br>    *   source venv\/bin\/activate is correct for macOS and Linux.<br>*   Package Management: The use of pip install for adding libraries and pip freeze &gt; requirements.txt for capturing dependencies is the correct workflow.<br>*   Deactivation: The deactivate command is the correct way to exit a virtual environment.<br>*   Portability Warning: The post correctly identifies a common &#8220;rookie mistake&#8221;\u2014trying to copy a venv folder to another machine. The advice to delete the folder and rebuild using pip install -r requirements.txt is exactly how it should be handled.<br><br>The &#8220;private room&#8221; analogy is an excellent way to explain the concept to beginners without overcomplicating the underlying system PATH modifications. Everything in the post is safe and correct for a beginner to follow. <br>\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\" \/>\n\n\n\n<p>My reason for doing this is to test Hermes Agent and document the findings in a future blog. Please leave a comment if you need more info about virtual environments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I remember the first time my Python script suddenly broke because another project of mine installed a conflicting, outdated version of a library. It was a frustrating headache where my script stopped working for no obvious reason. That was the day I decided to stop sharing global Python installations and start using virtual environments. For [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_ecmd_meta_description":"Learn to use Python virtual environments (venv) to manage packages. Includes a beginner guide to creating venv on Linux, Mac & Windows and a free project.","footnotes":""},"categories":[1],"tags":[11,12,13],"class_list":["post-515","post","type-post","status-publish","format-standard","hentry","category-guides","tag-beginner","tag-python","tag-venv"],"blocksy_meta":{"page_structure_type":"type-3","styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"_links":{"self":[{"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/posts\/515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/comments?post=515"}],"version-history":[{"count":13,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/posts\/515\/revisions"}],"predecessor-version":[{"id":537,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/posts\/515\/revisions\/537"}],"wp:attachment":[{"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/media?parent=515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/categories?post=515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/beginnerprojects.com\/cms\/wp-json\/wp\/v2\/tags?post=515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}