Skip to content
This repository

Add simple support for running inside a virtualenv #1388

merged 1 commit into from about 2 years ago

3 participants

Thomas Kluyver Min RK Fernando Perez
Thomas Kluyver

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.

Min RK

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.

Thomas Kluyver

Thanks, Min.

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

Fernando Perez

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...

Thomas Kluyver

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.

Fernando Perez

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.

Fernando Perez fperez merged commit 0a50e77 into from February 09, 2012
Fernando Perez fperez closed this February 09, 2012
Thomas Kluyver takluyver referenced this pull request April 23, 2012

Recognise virtualenvs #1171

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

Showing 1 unique commit by 1 author.

Feb 07, 2012
Thomas Kluyver Add simple support for running inside a virtualenv. 826ee2d
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 34 additions and 0 deletions. Show diff stats Hide diff stats

  1. 34  IPython/core/
34  IPython/core/
@@ -410,6 +410,9 @@ def __init__(self, config=None, ipython_dir=None, profile_dir=None,
410 410
411 411
412 412
+        # Check if we're in a virtualenv, and set up sys.path.
+        self.init_virtualenv()
413 416
414 417
         # Create namespaces (user_ns, user_global_ns, etc.)
415 418
         self.init_create_namespaces(user_module, user_ns)
@@ -661,6 +664,37 @@ def init_reload_doctest(self):
661 664
662 665
         except ImportError:
663 666
             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)
664 698
665 699
666 700
     # Things related to injections into the sys module

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.