Skip to content

Instantly share code, notes, and snippets.

@henriquebastos
Last active October 17, 2022 04:22
Show Gist options
  • Save henriquebastos/270cff100cb303f3d74370489022446b to your computer and use it in GitHub Desktop.
Save henriquebastos/270cff100cb303f3d74370489022446b to your computer and use it in GitHub Desktop.
IPython startup script to detect and inject VIRTUAL_ENV's site-packages dirs.
"""IPython startup script to detect and inject VIRTUAL_ENV's site-packages dirs.
IPython can detect virtualenv's path and injects it's site-packages dirs into sys.path.
But it can go wrong if IPython's python version differs from VIRTUAL_ENV's.
This module fixes it looking for the actual directories. We use only old stdlib
resources so it can work with as many Python versions as possible.
References:
http://stackoverflow.com/a/30650831/443564
http://stackoverflow.com/questions/122327/how-do-i-find-the-location-of-my-python-site-packages-directory
https://github.com/ipython/ipython/blob/master/IPython/core/interactiveshell.py#L676
Author: Henrique Bastos <henrique@bastos.net>
License: BSD
"""
import os
import sys
from warnings import warn
virtualenv = os.environ.get('VIRTUAL_ENV')
if virtualenv:
version = os.listdir(os.path.join(virtualenv, 'lib'))[0]
site_packages = os.path.join(virtualenv, 'lib', version, 'site-packages')
lib_dynload = os.path.join(virtualenv, 'lib', version, 'lib-dynload')
if not (os.path.exists(site_packages) and os.path.exists(lib_dynload)):
msg = 'Virtualenv site-packages discovery went wrong for %r' % repr([site_packages, lib_dynload])
warn(msg)
try:
i = sys.path.index("") + 1
except ValueError:
i = 0
sys.path.insert(i, site_packages)
sys.path.insert(i+1, lib_dynload)
@pollackscience
Copy link

Hi,
When using this script, I found that it ignored packages that were installed in 'develop' mode via python setup.py develop or pip install -e .. It seems like when something is installed in develop mode, an egg-link is added to the site-packages which points to the active package directory. I'm not sure how this egg-link is resolved normally in python, but at some point that directory is directly added to sys.path. To mimic this behavior, I added the following anywhere after the variable site_packages is defined:

egg_links = [i for i in os.listdir(site_packages) if 'egg-link' in i]
     for egg in egg_links:
         with open(os.path.join(site_packages,egg), 'r') as fin:
            sys.path.insert(0, fin.readline().rstrip('\n'))

This simply looks for anything that has 'egg-link' in the name, then opens the file and adds the first line to the path. No idea if you could have an edge case in which there could be multiple paths or lines in the egg-link, but this works for my needs.

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