Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Created April 21, 2019 15:36
Show Gist options
  • Save amcgregor/fd241a1e59dfabdf656e04e06e7a0052 to your computer and use it in GitHub Desktop.
Save amcgregor/fd241a1e59dfabdf656e04e06e7a0052 to your computer and use it in GitHub Desktop.

Howdy!

Alright, I think I found out the issue here. it's kind of annoying, I am not familiar enough with pip to know if there's an obvious easy solution.

Virtualenv is that solution. (To the point that it’s built-in to Python 3 as the “venv” module: python3 -m venv)

When installing html5lib from your requirements.txt, which points to a specific commit which is older than the system html5lib (1.0.1), pip decides that it would be a good idea to uninstall the system one, which obviously it cannot do.

Interestingly, html5lib is pinned by a third-party dependency not ourselves. This “one update” will result in a cascade of version bumps within our own requirements.txt, requiring some substantial testing before deployment. I’ll add this version bump to the backlog.

Back before Python 3 was a thing, virtualenv defaulted to including the global site-packages directory and users would typically invoke it with --ignore-site-packages to prevent exactly this type of conflict. (Today ignoring global site packages is the default.) It’s actually fairly impressive to me that you have a Python deployment architecture that doesn’t make use of virtual environments. Venv greatly improves isolation and reproducibility!

The update to the build process is simple:

virtualenv --python=python$PYTHON_VERSION venv_$APP_ID
source venv_$APP_ID/bin/activate
# proceed with app installation, “python” is now the chosen Python version via updated path.

The update to the run process is similarly simple: either ensure code is executed using the venv-contained bin/python executable (e.g. by sh-bang reference or explicit invocation), or the activate script is evaluated (and variables sourced into the current runtime) prior to launch. The on-disk structure is essentially unimportant; in development I utilize these environments in several structures:

  1. Application source container. The virtual environment itself is where I check out the application code into, either as the venv itself, or as a contained src folder to maintain the LFS-like structure. (With third-party checkouts going in $VIRTUAL_ENV/usr/src via the --src argument to pip.) Git is told to ignore the venv-specific files.

  2. A variation on the above places the virtual environment itself within the project folder as the .venv folder. Keeps things cleaner in Finder, keeps Git unaware.

  3. Centralized environments. Utilizing the hidden .venv approach, it is often a symlink to one from my central collection of environments within ~/Library/Environments.

All of the above is automated and integrated into my Zsh shell setup such that entering a directory that is a venv or contains a .venv will automatically activate, deactivating when exiting the path. Zero friction use, no need for additional tools like pipenv or virtualenvwrapper.

— Alice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment