Skip to content


Add simple support for running inside a virtualenv #1388

merged 1 commit into from

3 participants

IPython member

A snag that a number of users have hit is that a default installation of IPython ignores whether you have a virtualenv active. I've heard this from a user I was talking to, and there are workarounds posted on the web:

This basically integrates that workaround so it's activated whenever you start system-installed IPython with a virtualenv active. It's not perfect, so a warning is printed suggesting that users install IPython in the virtualenv.

There's an argument that if we can't handle it perfectly, we should simply get users to install IPython again in the virtualenv. But I think that this solution is good enough in the vast majority of cases that practicality should beat purity. People use IPython as a quick and easy way to check things, so anything which requires extra work on their part to run it is not ideal.

Another workaround is to change the shebang to #!/usr/bin/env python, but virtualenv now defaults to --no-site-packages, which will leave IPython un-importable. Also, the shebang won't affect Windows users.

IPython member

Seems sensible to me, I suppose. I have always leaned towards instructing people to just use virtualenv correctly, in which event this would never come up, but that seems to be a pretty rare occurrence.

IPython member

Thanks, Min.

@fperez , I'd like your thoughts on this one before I proceed with it.

IPython member

Mmh, what I don't really understand is, if these people are creating a virtualenv to install their other packages, what exactly prevents them from also installing ipython in there? I mean, either they want a virtualenv or they don't, and if they want one, they must populate it with the packages they want appearing in the venv, ipython being one of them...

I just fail to understand how ipython turns out to be in any way a special case regarding venv setup: we're not donig any special hackish sys.path manipulations ourselves, so we should be absolutely no different from any other python package that has an executable entry point, right? Doesn't sphinx-build have the exact same issues, or f2py, or the cython compiler call, or anything else that can be called as an executable, and where there's a conflict between the python used by the executable entry point and the library imports used by the virtualenv?

I do realize the need for practicality over purity, but this smacks me of crossing the line from practicality into flat out nasty hacks for the sake of helping people who are unwilling to do something as completely trivial as typing

python install


python develop

Neither of those seems so much to ask for, that we need to pollute our own code with an ugly workaround...

IPython member

All those tools have the same issue, but they're all things that you make a definite plan to use in a particular project, so it makes sense to install them (they might be in a requirements file). IPython is, for many users, a much more ad-hoc tool - you might drop into it to check a method signature, as a better alternative to the plain Python shell. And if you've got 60 virtualenvs for different projects, you don't want to have to install IPython in each one to get that convenience. The fact that multiple users have come up with workarounds for this also argues for its importance.

Put another way: for many users - perhaps most non-scientific users - IPython is a handy convenience. Anything that makes it less convenient reduces its utility for them exponentially.

I don't think the workaround is that ugly: it's one extra method, which will be a no-op if you're running IPython the preferred way.

IPython member

OK, I still don't like it, but I see the value in your argument. It seems @minrk was on a similar boat to me, not thrilled but willing to go along. Let's merge this for the sake of utility then, with a formal "not happy about it" from me.

Ultimately, I wish there was a cleaner solution for this overall problem at the python level itself, where its import/execution machinery was designed for clean isolation. But since that's not happening any time soon, off we go with the hacks.

@fperez fperez merged commit 0a50e77 into ipython:master
@takluyver takluyver referenced this pull request

Recognise virtualenvs #1171

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 7, 2012
  1. @takluyver
Showing with 34 additions and 0 deletions.
  1. +34 −0 IPython/core/
34 IPython/core/
@@ -410,6 +410,9 @@ def __init__(self, config=None, ipython_dir=None, profile_dir=None,
+ # Check if we're in a virtualenv, and set up sys.path.
+ self.init_virtualenv()
# Create namespaces (user_ns, user_global_ns, etc.)
self.init_create_namespaces(user_module, user_ns)
@@ -661,6 +664,37 @@ def init_reload_doctest(self):
except ImportError:
warn("doctest module does not exist.")
+ def init_virtualenv(self):
+ """Add a virtualenv to sys.path so the user can import modules from it.
+ This isn't perfect: it doesn't use the Python interpreter with which the
+ virtualenv was built, and it ignores the --no-site-packages option. A
+ warning will appear suggesting the user installs IPython in the
+ virtualenv, but for many cases, it probably works well enough.
+ Adapted from code snippets online.
+ """
+ if 'VIRTUAL_ENV' not in os.environ:
+ # Not in a virtualenv
+ return
+ if sys.executable.startswith(os.environ['VIRTUAL_ENV']):
+ # Running properly in the virtualenv, don't need to do anything
+ return
+ warn("Attempting to work in a virtualenv. If you encounter problems, please "
+ "install IPython inside the virtualenv.\n")
+ if sys.platform == "win32":
+ virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
+ else:
+ virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
+ 'python%d.%d' % sys.version_info[:2], 'site-packages')
+ import site
+ sys.path.insert(0, virtual_env)
+ site.addsitedir(virtual_env)
# Things related to injections into the sys module
Something went wrong with that request. Please try again.