Fix Broken Virtualenv Symlink After Brew Upgrade
Ever upgrade your python interpreter with homebrew and it messes up all your symlinks? Here’s how to fix it.
I don’t want to learn, skip to solution
If you’re using brew
to manage your packages on Mac (and if you’re not, you should) you might have encontered issues after updating Python in a virutalenv that look like this:
dyld: Library not loaded: @executable_path/../.Python
Referenced from: /Users/garettmd/venv/testapp/bin/python
Reason: image not found
Abort trap: 6
What’s happening here is the symlinks in your virtualenv are pointing to a non-existant executable. From the first line of the error you can see that it’s looking at the .Python
symlink in the base directory for the virutalenv. If you ls
on it, you’ll see something like
lrwxr-xr-x 79 garettmd 10 Aug 2017 .Python -> /usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/Python
If you ls
on that expanded location, you’ll see that it doesn’t exist. You could fix this by manually fixing the symlink to point to the new location (by changing the version in this case). However, if you take a look around some of the other directories in the virutalenv, you’ll see a lot of other symlinks in play, especially in the lib
directory. Rather than fixing these by hand, or even using some bash for loops, the simplest fix I’ve found (thanks to StackOverflow…) is to delete all the symlinks, and just run virtualenv
on the…virtualenv to regenerate all the symlinks again.
Solution
# This is for installing gfind (GNU find) which allows you to search for broken symlinks
brew install findutils
# First show the broken symlinks (you can skip this, but it's educational 😄)
gfind ~/.venv/my-virtual-env/ -type l -xtype l
# Then delete them
gfind ~/.venv/my-virtual-env/ -type l -xtype l -delete
# Now re-create them
virtualenv ~/.venv/my-virtual-env
Note that I’m using gfind
(GNU find) here because it allows you to show only broken symlinks. You could just as well use find ~/venv/testapp -type l -delete
, but that will also delete any symlinks that aren’t broken. This is probably fine most of the time, but if you’ve created your own symlinks outside of the virtualenv
command, those would get deleted too, but not recreated when you ran virtualenv
afterward.