从 viralenv 调用 IPython

我知道 IPython 不是 虚拟感知,对此最合乎逻辑的解决方案是分别使用

pip install ipython

目前为止还不错。我注意到的一点是,如果在 IPython 安装到这个 viralenv 之前,使用 $> ipython从一个 viralenv 调用 IPython 的系统范围的副本,随后的 $> ipython命令将继续调用系统范围的 IPython 副本。

另一方面,如果 ipython 在安装之前被 没有调用,那么将在一个 viralenv $> ipython下打开新安装的副本。

这是怎么回事?

这也让我怀疑,这种行为是否意味着我应该预料到一些麻烦?

43449 次浏览

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

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.

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.

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)

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

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.

  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.

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.