86

I understand that IPython is not virtualenv-aware and that the most logical solution to this is to install ipython in each virtualenv seperately using

pip install ipython

So far so good. One thing I noticed is that if the system-wide copy of IPython is called from within a virtualenv using $> ipython before IPython is installed under this virtualenv, subsequent $> ipython commands will continue to bring up the system-wide ipython copy.

On the other hand, if ipython is not called prior to installing it under a virtualenv $> ipython will bring up the newly installed copy.

What is the explanation for this?

It also makes me wonder if this behavior means I should expect some trouble down the way?

Mateusz Piotrowski
  • 6,087
  • 9
  • 44
  • 71
Mo Sander
  • 1,163
  • 1
  • 9
  • 13
  • 11
    Recent versions of IPython should recognise virtualenvs without needing to be installed separately - you'll see a "trying to work in a virtualenv" message when it starts. The 'sticky' command you see is bash caching the location of the `ipython` executable somewhere ([see this question](http://unix.stackexchange.com/questions/5609/how-do-i-clear-bashs-cache-of-paths-to-executables)). – Thomas K Dec 02 '13 at 20:39
  • Thomas, thanks for the link about bash caching, it seems that this is exactly what happens. IPython 1.1.0 shows me an 'Attempting to work in a virtualenv' warning but it does not recognise the virtualenv unless installed within a virtualenv - but that's fine I just wanted to make sure the procedure is unproblematic. – Mo Sander Dec 02 '13 at 23:07
  • 7
    what version of virtualenv are you using, and how are you activating the env? The command you are missing is `hash -r`, which drops the cache of previously run commands, which is typically executed as part of activating an env. Check for `hash -r` in ENV/bin/activate. – minrk Dec 18 '13 at 05:22
  • 1
    yes, true! As Thomas pointed out, this was a bash caching issue and running `hash -r` before activating an env resolves the problem. FYI I was working with virtualenv 1.10.1 – Mo Sander Dec 29 '13 at 16:27

8 Answers8

112

alias ipy="python -c 'import IPython; IPython.terminal.ipapp.launch_new_instance()'"

This is a great way of always being sure that the ipython instance always belongs to the virtualenv's python version.

This works only on ipython >2.0.

Source

Community
  • 1
  • 1
SiddharthaRT
  • 1,979
  • 3
  • 18
  • 28
32

The answer given by @SiddharthaRT is good! Following this approach, it is simpler for me just:

python -m IPython

This will use the module IPython through the python bin, ensuring that it refers to the bin from the virtual env.

jcozar87
  • 416
  • 4
  • 7
10

You can force IPython to use a virtual environment if available by adding file below to ~/.ipython/profile_default/startups:

import os
import sys

if 'VIRTUAL_ENV' in os.environ:
    py_version = sys.version_info[:2] # formatted as X.Y 
    py_infix = os.path.join('lib', ('python%d.%d' % py_version))
    virtual_site = os.path.join(os.environ.get('VIRTUAL_ENV'), py_infix, 'site-packages')
    dist_site = os.path.join('/usr', py_infix, 'dist-packages')

    # OPTIONAL: exclude debian-based system distributions sites
    sys.path = filter(lambda p: not p.startswith(dist_site), sys.path)

    # add virtualenv site
    sys.path.insert(0, virtual_site)

I recommend naming it 00-virtualenv.py so changes will be made as early as possible.

Note: Make sure ipython is installed in the new virtual environment to get this to work.

Weevils
  • 157
  • 2
  • 9
rgtk
  • 2,896
  • 1
  • 28
  • 35
  • 1
    This works great in Python 2 environments, but in version 3 envs I get an ImportError stating theres no module named "IPython". Running ipython3 outside the environment works, do you know what I'm missing here? – efr4k Jul 01 '16 at 09:55
  • Thanks for this. But I think the "Optional" line breaks with python3 as sys.path becomes a filter object which doesn't respond to list methods, right? – mota Aug 06 '19 at 15:00
6

As others mentioned, recent versions of ipython are virtualenv aware, so you can use your virtualenv bin activate script to run ipython using your virtualenv, e.g.

$ source venv/bin/activate
(venv) $ ipython
WARNING: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
JDiMatteo
  • 9,062
  • 3
  • 47
  • 55
  • 2
    So many downvotes. If this doesn't work for you, please comment with an error message and output of `ipython --version; cat /etc/issue` – JDiMatteo Nov 12 '17 at 01:56
  • 2
    This will work with IPython's console, but will not work with other things, for example IPython kernel. – Błażej Michalik Jun 15 '18 at 21:18
6
  1. Activate your virtual environment by using source ~/.virtualenvs/my_venv/bin/activate or by running workon my_venv (Depending on how you've installed the my_venv virtual environment)

  2. Install ipython

pip install ipython

  1. Now run ipython from my_venv.

If it still loads the system's ipython,then run

hash -r

TheDataGuy
  • 161
  • 2
  • 7
  • This worked for me but option `-r` is "forget all remembered locations" from the GNU docs. Not sure what is actually forgotten. Do you know @TheDataGuy? – izzleee Apr 05 '21 at 05:31
2

I'll chime in years later in hopes someone finds this useful.

This solution solves a few problems:

  • You don't need iPython installed in the current virtualenv, only for the global Python that matches your virtualenv's Python version (3.6 != 3.7).
  • Works for users of pyenv where your global Python version might be 3.7 and your local virtualenv Python is 3.6 therefore using the global ipython will fail.
  • Works outside of virtual environments (though not particularly useful as it always targets python).

Throw this in your ~/.bashrc or ~/.zshrc or what have you:

# This is a roundabout way to start ipython from inside a virtualenv without it being installed
# in that virtualenv. The only caveot is that the "global" python must have ipython installed.
# What this function does that's different than simply calling the global ipython is it ensures to
# call the ipython that is installed for the same major.minor python version as in the virtualenv.
# This is most useful if you use pyenv for example as global python3 could be 3.7 and local
# virtualenv python3 is 3.6.
function ipy {
  local PY_BIN
  local IPYTHON
  local PYV
  # This quick way will work if ipython is in the virtualenv
  PY_BIN="$(python -c 'import sys; print(sys.executable)')"
  IPYTHON="$(dirname "$PY_BIN")/ipython"
  if [[ -x "$IPYTHON" ]]; then
    "$IPYTHON"
  else
    # Ask the current python what version it is
    PYV="$(python -c 'import sys; print(".".join(str(i) for i in sys.version_info[:2]))')"
    echo "Looking for iPython for Python $PYV"
    # In a new shell (where pyenv should load if equipped) try to find that version
    PY_BIN="$($SHELL -i -c "python$PYV -c 'import sys; print(sys.executable)'")"
    "$(dirname "$PY_BIN")/ipython"
  fi
}

Then source or open a new terminal and run ipy.

Skinner927
  • 844
  • 2
  • 13
  • 23
1

If you're trying to open a notebook, even ipython 5 won't help - ipython will disregard the virtualenv (at least on my machine/setup). You'll need to use rgtk's script, but please make sure to modify the optional filter part and the sys.path.insert as below:

import os
import sys

if 'VIRTUAL_ENV' in os.environ:
    py_version = sys.version_info[:2] # formatted as X.Y 
    py_infix = os.path.join('lib', ('python%d.%d' % py_version))
    virtual_site = os.path.join(os.environ.get('VIRTUAL_ENV'), py_infix, 'site-packages')
    dist_site = os.path.join('/usr', py_infix, 'dist-packages')

    # OPTIONAL: exclude debian-based system distributions sites
    # ADD1: sys.path must be a list
    sys.path = list(filter(lambda p: not p.startswith(dist_site), sys.path))

    # add virtualenv site
    # ADD2: insert(0 is wrong and breaks conformance of sys.path
    sys.path.insert(1, virtual_site)
Community
  • 1
  • 1
1

(Debian/Ubuntu) assuming some version (x) of Python3 is installed, then:

$ sudo apt-get install -y ipython
$ virtualenv --python=python3.x .venv
$ source .venv/bin/activate
$ pip3 install ipython
$ ipython3

will launch ipython running your version of Python3.

mjkrause
  • 166
  • 2
  • 12