108

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?

4
  • 12
    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). Commented Dec 2, 2013 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. Commented Dec 2, 2013 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. Commented Dec 18, 2013 at 5: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 Commented Dec 29, 2013 at 16:27

8 Answers 8

138

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

Sign up to request clarification or add additional context in comments.

1 Comment

BTW, profile name can be passed via kwargs. Thanks for that answer!
65

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.

Comments

28
  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 in your shell

This will reset the cache of your shell and ensure you don't run another ipython that was already called in this shell session.

4 Comments

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?
After searching for half an hour, the hash -r command did it for me, thanks!
@SanderLam Yes and it works in OSX Ventura too! Seems to be the simplest solution for zsh
@thedataguy Thanks for the hash -r tip. That solved a similar problem for me.
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.

2 Comments

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?
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?
9

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.

2 Comments

So many downvotes. If this doesn't work for you, please comment with an error message and output of ipython --version; cat /etc/issue
This will work with IPython's console, but will not work with other things, for example IPython kernel.
5

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.

Comments

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)

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.