从虚拟环境中调用IPython

99

我明白IPython不支持virtualenv,最合理的解决方案是在每个虚拟环境中单独安装IPython。

pip install ipython

目前为止一切都很顺利。我注意到的一件事是,如果在虚拟环境中安装IPython之前使用$> ipython调用系统范围内的IPython,那么随后的$> ipython命令将继续启动系统范围内的ipython副本。

另一方面,如果在虚拟环境下安装IPython之前调用ipython,则$> ipython将启动新安装的ipython副本。

这是什么原因呢?

这也让我想知道这种行为是否意味着我将来会遇到麻烦?


12
最近版本的IPython应该能够识别虚拟环境,无需单独安装 - 当它启动时,您将看到一条“尝试在虚拟环境中工作”的消息。您看到的“sticky”命令是bash在某个位置缓存ipython可执行文件的位置(请参见此问题)。 - Thomas K
Thomas,感谢你提供的有关bash缓存的链接,看起来这正是发生的情况。IPython 1.1.0向我显示了一个“尝试在虚拟环境中工作”的警告,但它不会识别虚拟环境,除非安装在虚拟环境中——但这没关系,我只是想确保该过程没有问题。 - Mo Sander
7
你在使用哪个版本的virtualenv,并且你是如何激活环境的?你缺少的命令是 hash -r,它会清除之前运行命令的缓存,通常作为激活环境的一部分执行。请检查 ENV/bin/activate 中是否有 hash -r 命令。 - minrk
1
是的,没错!正如Thomas指出的那样,这是一个bash缓存问题,运行hash -r在激活环境之前可以解决这个问题。FYI,我正在使用virtualenv 1.10.1。 - Mo Sander
8个回答

132

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

这是一种很好的方式,可以确保ipython实例始终属于虚拟环境中的Python版本。

这仅适用于ipython >2.0。

来源


1
顺便提一下,配置文件名称可以通过kwargs传递。感谢您的答案! - roboslone

52

@SiddharthaRT给出的答案很好!按照这个方法,对我来说更简单的是:

python -m IPython

这将通过Python bin使用IPython模块,确保它引用来自虚拟环境的bin文件夹。


25
  1. 通过使用source ~/.virtualenvs/my_venv/bin/activate或运行workon my_venv(根据您安装my_venv虚拟环境的方式而定),激活虚拟环境。

  2. 安装ipython。

pip install ipython

  1. 现在从my_venv中运行ipython。

如果它仍然加载系统的ipython,则在您的Shell中运行hash -r

这将重置您的Shell缓存,并确保您不会在此Shell会话中再次运行已经调用的其他ipython。


1
这对我有用,但选项-r是从GNU文档中的“忘记所有已记住的位置”。不确定实际上忘记了什么。你知道@TheDataGuy吗? - izzleee
2
在搜索了半个小时之后,hash -r 命令为我解决了问题,谢谢! - Sander Lam
@SanderLam 是的,它在OSX Ventura上也可以工作!似乎是zsh的最简单解决方案。 - tehfink

10

如果可用,您可以通过在以下文件中添加内容,强制 IPython 使用虚拟环境:

~/.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)

我建议将其命名为00-virtualenv.py,这样更改就能尽早进行。

注意:确保在新虚拟环境中安装了ipython,才能使此工作正常运行。


1
这在Python 2环境中运行得很好,但在版本3环境中,我收到一个ImportError,指出没有名为“IPython”的模块。在环境外运行ipython3是可以的,你知道我错过了什么吗? - efr4k
谢谢您的回复。但是我认为“Optional”行在Python3中会出现问题,因为sys.path变成了一个过滤器对象,无法响应列表方法,对吧? - mota

8

正如其他人所提到的,最近版本的IPython支持虚拟环境,因此您可以使用虚拟环境bin下的激活脚本来运行IPython,例如:

$ source venv/bin/activate
(venv) $ ipython
WARNING: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.

2
这么多踩。如果这对你不起作用,请在评论中附上错误消息和 ipython --version; cat /etc/issue 的输出。 - JDiMatteo
2
这将适用于IPython的控制台,但不适用于其他东西,例如IPython内核。 - Błażej Michalik

4

我希望几年后有人能发现这篇文章有用。

这个解决方案解决了以下几个问题:

  • 你不需要在当前虚拟环境中安装iPython,只需要安装与你的虚拟环境Python版本相匹配的全局Python (3.6 != 3.7)。
  • 适用于使用pyenv的用户,如果你的全局Python版本是3.7,而你本地虚拟环境Python是3.6,那么使用全局的ipython将会失败。
  • 适用于虚拟环境之外的使用 (虽然它总是针对python, 但没有太大实用性)。

将其放入您的~/.bashrc~/.zshrc或其他文件中:

# 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
}

然后打开终端并运行ipy或者source命令。


1
(Debian / Ubuntu)假设已安装某个版本(x)的Python3,则:
$ sudo apt-get install -y ipython
$ virtualenv --python=python3.x .venv
$ source .venv/bin/activate
$ pip3 install ipython
$ ipython3

将启动运行您的Python3版本的IPython。


1
如果你想打开一个笔记本,即使是 ipython 5 也无法帮助 - ipython 将忽略 virtualenv(至少在我的机器/设置上)。 你需要使用 rgtk 的脚本,但请确保按照以下方式修改可选过滤器部分和 sys.path.insert:
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)
  • ADD1:在原始脚本中,我们会得到一个过滤器对象,如果我们打破sys.path并插入下面的内容将会失败。
  • ADD2: 请参见这个问题Python文档

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接