Setting Up a Local Python Environment (For Idiots)
I've decided to celebrate the holiday season by throwing together a simple HTTP server using the Bottle library. I haven't written anything object oriented in quite some time, and I was feeling like using some decorators again. My intention was to write a bit about my experience using the Bottle library, but of course this devolved largely into an exploration of the "peculiarities" of setting up a local Python environment...
Local Python Versioning - Why?
Disclaimer: as with everything you come across on this meandering blog, I am no expert. Python local environment setup and maintainence is a pretty emotional topic for some. I personally have been scarred by it enough times in the past that my usual strategy was to simply get things working and leave it all the fuck alone without peeking under the covers. Today I will try and explain things a bit more.
Anyhoo. For background, it's important to understand why people jump through hoops to maintain a specific local environment for Python application development. After all, Python ships with most Linux distributions, and until recently shipped with Mac OS. However, using the system installed version of Python will generally lead to a bad time. Using the system installed version pins you to a single version of Python, and is often plagued by various permissions issues (if you insist on using the system version, get used to the chmod
and chown
unix commands).
Enter Pyenv
There are a few different tools that are popular for local Python version management, but I have always chosen Pyenv. Maybe this is because it's inspired by Rbenv, which is the blessed Ruby environment manager (or at least it was like 10 years ago when I last wrote Ruby.)
Pyenv solves a few fundamental problems with the default system installation of Python. Essentially, Pyenv provides a way to isolate different versions of Python on the same system. You can switch between Python versions for a given project, and you can scope any dependencies to a given project as well. I like to think of environment managers like this as ways to essentially put individual projects in bubbles. The bubble contains all the requisite environmental configuration to run it, but that configuration can't leak out and affect other bubbles. As you can see, I have the mind of a small child.
Shims and your PATH
Pyenv works by inserting a "shim" into your system PATH
. Obviously this sounds like nonsense. However, I have always found this architecture interesting as it gets to the heart of how any Unix-based operating system works under the hood.
When you run a program on a Mac or Linux computer, you are essentially telling the operating system to find and execute a file. This file is called an executable. Graphical User Interfaces obfuscate this process, but you can see it on the command line. When you open a terminal and type cat somefile.txt
, you are invoking the executable file for the cat
program and having it operate on somefile.txt
.
But where is this cat
program? Where should the operating system look to find it? The answer is your system PATH
. This value is a list of directories separated by colons. Each directory is a place the operating system will look to find an executable with the name invoked. As soon as a matching one is found, the corresponding executable is "executed" and the program is then run.
Pyenv works by "shimming" a directory it manages "ahead" of the system Python directory. That way, the code and Python versions managed by Pyenv will be reached first as the OS traverses the PATH and will be invoked before the system Python directory is even reached.
Below is an example of what a PATH
value might look like (check yours in the terminal - echo $PATH
)
echo $PATH
/Users/andy.fritz/.cargo/bin:
/Users/andy.fritz/.local/bin:
/Users/andy.fritz/.pyenv/shims:
/opt/homebrew/bin:/...
Pyenv has "shimmed" its directory near the beginning of my PATH
as /Users/andy.fritz/.pyenv/shims
. Now the Operating System will look in there and find the Python version I want to use.
Instructions
Alright, I've explained the intention of installing Pyenv above. Below are the steps to actually do this...
- Install Pyenv
You can do this a few ways, but this command in your terminal should work
curl https://pyenv.run | bash
The above will just fetch a script to execute in bash to download the package. If you're not using bash, execute it with zsh or whatever your shell is.
- Install a Python version
Pyenv doesn't actually come with any versions installed by default. However, once Pyenv is installed, you can list available versions with
pyenv install -l
Pick a version from the list and install it globally with
pyenv global WHATEVER_VERSION
- Enjoy!
(maybe)
Conclusion(s)
Well I have once again digressed, this time to the point of not even installing the Bottle package. Oh well, next time!