UPDATE 2012-06-01: Doug released virtualenvwrapper 3.4 with built-in support for lazy loading. It’s a lot better than the hack in this post!
Loading virtualenvwrapper.sh
takes too long:
$ time source /usr/bin/virtualenvwrapper.sh
real 0m1.034s
user 0m0.625s
sys 0m0.161s
If you load virtualenvwrapper.sh
in your .bashrc
, this means waiting an
extra second every time you open a terminal. But you can avoid the delay by
loading the functions on demand! The trick is to create stub functions
workon
, deactivate
and mkvirtualenv
that will load
virtualenvwrapper.sh
and then run the real function.
To make this work, save the following snippet as
.bashrc.virtualenvwrapper
in your home directory:
# Dynamically load virtualenvwrapper functions to reduce shell startup
# time.
#
# Copyright 2012 Aron Griffis <aron@arongriffis.com>
# Released under the GNU GPL v3
#######################################################################
# Python virtualenvwrapper loads really slowly, so load it on demand.
if [[ $(type -t workon) != function ]]; then
virtualenv_funcs=( workon deactivate mkvirtualenv )
load_virtualenv() {
# If these already exist, then virtualenvwrapper won't override them.
unset -f "${virtualenv_funcs[@]}"
# virtualenvwrapper doesn't load if PYTHONPATH is set, because the
# virtualenv python doesn't have the right modules.
declare _pp="$PYTHONPATH"
unset PYTHONPATH
# Attempt to load virtualenvwrapper from its many possible sources...
_try_source() { [[ -f $1 ]] || return; source "$1"; return 0; }
_try_source /usr/local/bin/virtualenvwrapper.sh || \
_try_source /etc/bash_completion.d/virtualenvwrapper || \
_try_source /usr/bin/virtualenvwrapper.sh
declare status=$?
unset -f _try_source
# Restore PYTHONPATH
[[ -n $_pp ]] && export PYTHONPATH="$_pp"
# Did loading work?
if [[ $status != 0 || $(type -t "$1") != function ]]; then
echo "Error loading virtualenvwrapper, sorry" >&2
return $status
fi
# Chain-load the appropriate function
"$@"
}
for v in "${virtualenv_funcs[@]}"; do
eval "$v() { load_virtualenv $v \"\$@\"; }"
done
fi
Then replace source virtualenvwrapper.sh
in your .bashrc with:
source ~/.bashrc.virtualenvwrapper
This loads in about 1/100 of a second, and the real virtualenvwrapper.sh
will load when you first invoke workon
or mkvirtualenv
.
Originally posted on the n01se blog.