Avatar

Gilles Fabio

Full-Stack Developer

RVM for Pythonistas, virtualenv for Rubyists

You are or have been a Pythonista? You are or were in love with virtualenv, virtualenwrapper or Buildout? Now you do some Ruby you are looking for the same wonderful tools? You should take a look at RVM or Ruby Version Manager.

Oh, well. You are or have been a Rubyist? You are or were in love with RVM? Now you do some Python you are looking for the same wonderful tool? You should take a look at virtualenv (with virtualenvwrapper).

Installation

I am a Pythonista

First, make sure pip is installed on your system.

Then, in your terminal:

sudo pip install virtualenvwrapper

Create the directory which will contain your virtual environments. For example, $HOME/.virtualenvs:

mkdir ~/.virtualenvs

Edit your $HOME/bash_profile file and add these lines:

export WORKON_HOME=$HOME/.virtualenvs
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true

Source it:

source ~/.bash_profile

Troubleshooting? Check the documentation.

I am a Rubyist

First, make sure Git is installed on your system.

Then, in your terminal:

bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

Edit your $HOME/.bash_profile file and add this line at the very end:

[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"

Source it:

source ~/.rvm/scripts/rvm

Troubleshooting? Check the documentation.

Managing multiple interpreters

I am a Pythonista

You have to install the different Python versions on your system (via your package manager). When you will create a virtual environment with virtualenv, you will pass the interpreter path of the desired Python version as -p argument of mkvirtualenv command.

Example:

mkvirtualenv -p /opt/local/bin/python3 myproject

I am a Rubyist

RVM compiles and installs the desired Ruby interpreter and Ruby version in the current user directory. It supports MRI/YARV, Rubinius, JRuby, Ruby Enterprise Edition, MagLev, IronRuby, MacRuby and GoRuby. This can be achieved in a single one command.

To list the available interpreters and versions to which it may install:

rvm list known

Let’s install the original implementation in version 1.8.7 and 1.9.2 (make sure Subversion is installed):

rvm install 1.8.7
rvm install 1.9.2

This takes some compilation time and you’ve done.

To list the installed Ruby versions:

rvm list rubies

To switch between interpreters:

rvm use RUBY_VERSION

For example, switching to 1.8.2:

rvm use 1.8.2

Or switching to 1.9.2:

rvm use 1.9.2

To set up the default interpreter:

rvm --default use RUBY_VERSION

For example, if you want to use Ruby 1.9.2 as default interpreter:

rvm --default use 1.9.2

To switch back to your default system interpreter:

rvm use system

This is very powerful. Check the documentation to know more about available commands and options.

Managing multiple environments

I am a Pythonista

Generally, with virtualenv, you create one environment per project and/or project stage (development, testing, staging, production, etc). This can be accomplished with the mkvirtualenv command:

mkvirtualenv --no-site-packages PROJECT_NAME

For example, if my project name is “superdjango”:

mkvirtualenv --no-site-packages superdjango

The --no-site-packages option removes the standard site-packages directory from the environment sys.path. I recommend to use this option if you want more isolation. It avoids dealing with system packages conflicts.

As seen above, you can specify the Python version with the -p option:

mkvirtualenv --no-site-packages -p /opt/local/bin/python3 PROJECT_NAME

If you added export PIP_RESPECT_VIRTUALENV=true in your $HOME/.bash_profile file, when your environment is active, pip auto-installs packages in this environment. You do not have to prefix it with any sudo command or have to pass it any option. Just this:

pip install PACKAGE

Example:

pip install Django

Otherwise, you need to use the -E option:

pip install -E ENVIRONMENT_NAME PACKAGE

Example:

pip install -E superdjango Django

To list all available environments, use the workon command:

workon

To activate an environment:

workon ENVIRONMENT_NAME

Example:

workon superdjango

The first time you create a virtual environment with the mkvirtualenv command, you will auto-switch to this environment instantly (the environment name prefixes your session prompt).

To deactivate the current environment, use the deactivate command:

deactivate

To delete a virtual environment:

rmvirtualenv ENVIRONMENT_NAME

Example:

rmvirtualenv superdjango

I am a Rubyist

Where virtualenv has “environments”, RVM has “gemsets”. Interpreters and packages are all separated and self-contained from system and from each other. Creating a virtual environment with virtualenv is creating a gemset with RVM. Generally, you create one gemset per project and/or project stage (development, testing, staging, production, etc). This can be done with this command:

rvm use RUBY_VERSION@GEMSET_NAME --create

Example:

rvm use 1.9.2@myproject --create

This is equivalent to:

rvm use 1.9.2
rvm gemset create myproject
rvm gemset use myproject

When your gemset is active, using gem install command will install packages directly in your gemset. So you can use:

gem install PACKAGE

This will install the given package in your current active gemset directory.

To know the path of this directory, you can use the gemdir RVM command:

rvm gemdir

Deleting a gemset is simple as:

rvm gemset delete GEMSET_NAME

Example:

rvm gemset delete myproject

To empty a gemset (removing all installed gems):

rvm gemset empty GEMSET_NAME

Example:

rvm gemset empty myproject

Managing project dependencies

I am a Pythonista

Managing project dependencies with Pip and virtualenv is crazy simple. You just have to create a text file containing package names (and optionally package versions) and give this file to Pip via the -r option. Everything is clearly well explained in the documentation.

To give you an example, for my “superdjango” project, I create a requirements.txt file to start my project with Django 1.2.x and South support. This requirements.txt file looks like this:

Django >= 1.2
South == 0.7.2

If I don’t already created my environment, I create it right now:

mkvirtualenv --no-site-packages superdjango

And I install project dependencies:

pip install -r /path/to/my/requirements.txt

This will install the latest Django 1.2 version and South 0.7.2 into my virtual environment.

I am a Rubyist

Managing project dependencies with RVM, RubyGem and Bundler is crazy simple too.

Where Pip has “requirements” files, Bundler has “Gemfile” files.

First, you need to create a dedicated gemset for the project:

rvm use RUBY_VERSION@GEMSET_NAME --create

Example:

rvm use 1.9.2@myproject --create

This is the same of these commands:

rvm use 1.9.2
rvm gemset create myproject
rvm gemset use myproject

I install Bundler into my gemset:

gem install bundler

I create a directory for my project:

cd /path/to/my/workspace
mkdir myproject

I go in the directory and create an empty Gemfile file:

cd myproject
bundle init

Then I edit the Gemfile file and add my dependencies:

source "http://rubygems.org"

gem "sinatra", "~> 0.9.0"
gem "rack-cache"
gem "rack-bug"

Now, I install dependencies in the current gemset:

bundle install

That’s all. Everything is clearly well explained in the documentation.

Conclusion

RVM and virtualenv (coupled with virtualenvwrapper) are both powerful tools which considerably improve your productivity and reduce headache fighting with dependencies. Today, I can’t even imagine living without. I didn’t cover Buildout, the Python alternative to virtualenv, because it works a different way but it’s a wonderful tool you should give it a try. These articles, written by Jacob Kaplan-Moss, are must-read: