Python Environment Management for Rubyists – a Guide

Python has always been an intriguing language to me, but I’ve never been a huge fan of its syntax. I have always liked Lisps, though. Thus, when I discovered Hy a few months ago, I was completely smitten. Then I tried to set up a development environment, and was caught in a morass of old tooling and poorly explained transitions. Python 2? Python 3? Pip? Setuptools? Easy_install? Ugh.

Thankfully, I’ve now discovered a few tools that make managing multiple versions of Python and your projects libraries a breeze (on Mac/Linux systems, at least). In this post, I’ll walk you through a basic Python setup to get you rolling on a new project.

Python Package Management

When confronting the problem of managing library dependencies, I was massively confused. Over the course of Python’s evolution, there have been many tools for managing and distributing packages. Googling around, you’ll find (at minimum) references to distutils, setuptools, easy_install, and pip.

Luckily, until you want to start distributing your own libraries, you can pretty much forget about everything but pip. As Anton Kovalyov quipped on Twitter, “easy_install is the internet explorer of Python package managers.” (It is only used to install pip when setting up your development environment)

Pip has an extremely easy to use interface, similar to other well-known package managers like bundler or npm.

Python Version Management

In Ruby, tools like rbenv make it a snap to install and manage which version of Ruby is being used for a project. By simply dropping a file called .ruby-version containing your desired Ruby version in your project directory, rbenv will automatically update shims to point at the correct Ruby install. Combined with bundler to manage package versions, you have a full language versioning system.

For quite some time, Python has had the ability to isolate the module dependencies for a project using a utility called virtualenv. Virtualenv allows you to source a shell script to activate a particular Python environment, with isolated packages and a specific Python version, which I found pretty awesome. Virtualenv does not, however, provide any facilities for managing installed Pythons.

Thankfully, an enterprising developer forked rbenv to create pyenv, which works very similarly to rbenv. When combined with pyenv-virtualenv, it allows you to automatically activate a Python virtualenv on a per-project basis.

To install pyenv and pyenv-virtualenv with Homebrew on a Mac:

  1. brew install pyenv
  2. brew install pyenv-virtualenv
  3. Add the following lines to your .bash_profile to put the pyenv shims in your $PATH:

    if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi
    if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
  4. Close and reopen your terminal so the $PATH changes propagate

And to set up a fresh Python environment for a new project:

  1. pyenv install 3.4.2
  2. cd /my/project/dir
  3. pyenv virtualenv 3.4.2 my_project_env
  4. Drop a .python-version containing my_project_env into your current directory
    pyenv local my_project_env

Congratulations. Now whenever you cd into this project directory, pyenv-virtualenv will activate the “my_project_env” virtualenv, and all your package installs will be scoped to the “my_project_env” virtualenv.

  • Carl D says:

    This is great. Have you found any useful analogs for bundler, rspec, cane, or rake? :-)

    • Mitchell Johnson Mitchell Johnson says:

      Thanks, Carl.

      In python, the role of bundler is taken by a combination of pip and virtualenv. For dependency management, pip conventions are to have a file called requirements.txt, which you can read about here. There’s no messing about with bundle exec to activate a dependency set, instead you just hop into a dedicated virtualenv for the project.

      For testing, python has quite a few different libraries available. I’m unsure that there’s a direct equivalent of rspec, but the standard library has unittest (docs here), which has worked quite well for my small projects. From my limited reading, if I were to start a new project today, I’d probably use nose (docs here). The python wiki has a larger list of available frameworks here.

      Several options exist for code coverage, but I usually see used. Docs here.

      I haven’t had to use any rake-alikes, though Invoke looks absolutely intriguing. Docs here.

      Good luck on your python adventures. :-)

  • Comments are closed.