A python developer’s guide to hacking on an airplane

After spending 18 hours on planes and airport lounges commuting between Singapore and MEST in Accra, I grew extremely frustrated by the fact that I could not create virtualenvs and install packages in them using pip without internet access.

The first thing I thought of was to configure pip to create a local cache. This was very simple to do. To configure pip to use a cache, either add

export PIP_DOWNLOAD_CACHE=$HOME/Library/Caches/pip-downloads

to your .bash_profile or .bashrc OR create, if it doesn’t already exists, a pip.conf file in your ~/.pip directory and add:

download_cache = ~/Library/Caches/pip-downloads

This is pretty cool and caches all the packages you download so that you do not have to wait for 2 minutes each time you run pip install django-toolbelt. However, it is still not network independent.

pip still checks with the PyPI servers to see if the cached packages are the latest ones and if they are not, it downloads the newer versions from a PyPI server and updates the cache.

While this is awesome, it is not optimal if you need to download packages using pip without having internet access and are okay with using a version that is not bleeding edge. This is where pip2pi comes in.

pip2pi creates a local PyPI index so that you can “fool” pip into thinking that it is talking to an actual PyPI server and download your repositories locally, without internet access.

To do so, download pip2pi using:

pip install pip2pi

Now, create a folder which is going to house your PyPI index. I created ~/.localpip/packages.

To add a package to this index, all you have to do is call

pip2pi ~/.localpip/packages/ package_name
# OR
pip2pi ~/.localpip/packages/ package_name==package.version
# OR
pip2pi ~/.localpip/packages/ -r requirements.txt

And thats it, this package is now a part of your local PyPI index.

 Some Explanation

The pip2pi command is actually running 2 commands in the background (which you can run yourself if you want to).

It first runs:

pip2tgz ~/.localpip/packages package_name

which downloads the package from PyPI into the ~/.localpip/packages folder as a .tgz file.

Next, it runs

dir2pi ~/.localpip/packages

to build the PyPI index into the ~/.localpip/packages/simple folder.

Now, to install any thing using the local index, run:

pip install --index-url=file:///Users/nknj/.localpip/packages/simple package_name
# OR
pip install --index-url=file:///Users/nknj/.localpip/packages/simple package_name==package.version
# OR
pip install --index-url=file:///Users/nknj/.localpip/packages/simple -r requirements.txt


 Making it even easier

To make things even easier, I decided to create a few aliases to help me out.

First, I created an alias called localpip to help with installing from the local index without having to write to the index-url bit over and over:

export LOCAL_PIP_REPO=$HOME/.localpip/packages
alias localpip="pip install --index-url=file://"$LOCAL_PIP_REPO"/simple"

Next, to make it easier for me to remember to add packages to my local index I created the alias pi that installs the package from pip and then runs the pip2pi command to add it to the index in case I need to use again on the airplane.

export LOCAL_PIP_REPO=$HOME/.localpip/packages
function pip_pip2pi() {
  pip install "$@" && pip2pi $LOCAL_PIP_REPO "$@"
alias pi=pip_pip2pi


Thats it! Now, as long as I make it a habit to use pi instead of pip I can use localpip whenever I do not have internet access and continue coding. My flight back home is definitely going to be more productive.


Now read this

Token Authentication with Django and AngularJS

For the past month, I have been building all my new apps in a fully decoupled fashion. I build my backend using Django which acts like a RESTful API server and I build my frontend using AngularJS which consumes that RESTful API. The... Continue →