如何让Homebrew的Python和Pyenv共存?

52

从比较简单的2.7.9版本切换到Python 3.4.3后,我经常希望在与同事分享之前用2.7.9测试我的脚本。我使用的是OSX Yosemite平台,所有内容均由Homebrew编译。

这种情况非常麻烦(需要在每一步设置路径和PYTHONPATH)- 直到我发现了pyenv,它可以轻松地完成这个任务,并且可以很容易地使用Homebrew进行安装。目前为止,一切都很好。

但是,现在我使用的这个Python版本不一定与Homebrew兼容。此外,我发现我可以切换回系统的Python版本,并且通常情况下pyenv也可以访问它:

$ pyenv versions
  system
  2.7.9
* 3.4.3 (set by /usr/local/var/pyenv/version)

但是我该如何为Homebrew编译的Python添加条目呢?

7个回答

62

按照pyenv的安装指南,您可以将其安装在您的主目录下,然后创建一个符号链接 ~/.pyenv/versions 指向 $(brew --cellar)/python:

ln -s $(brew --cellar python)/* ~/.pyenv/versions/

现在的Homebrew工作方式是,这将同时选择2.x和3.x版本。


如果versions文件夹已经存在,这个方法就不起作用了,并且也不会包含python3。另外,我相信你的意思是:ln -s $(brew --cellar)/python ~/.pyenv/versions。 - misnomer
2
实际上,您需要运行 ln -s $(brew --cellar python)/* ~/.pyenv/versions。否则,添加的 Python 版本将被称为 python 而不是 2.7.0 - Hanxue
由于我试图在pyenv中列出我自己安装的python3环境,以下命令对我有用:ln -s $(brew --cellar python3)/* ~/.pyenv/versions这个命令对我起了作用。 - JacobWuzHere
2
对于Homebrew的Python 2,配方现在被称为python@2。如果 brew list -1 | grep python@2 打印出 python@2 而不是空白,则表示你已经安装了Homebrew的Python 2版本。如果你想在pyenv中使用它,你需要稍微修改答案中的命令为:ln -s $(brew --cellar python@2)/* ~/.pyenv/versions/ - WalterGR
7
有没有办法让Homebrew使用通过pyenv安装的Python?我尝试了 ln -s ~/.pyenv/versions/3.7.3 $HOME/homebrew/Cellar/python,但Homebrew仍然会尝试安装自己的Python。 - laike9m
6
为包括所有通过Homebrew安装的Python版本,我使用“ln -s $(brew --cellar)/python*/* /.pyenv/versions/”命令将Homebrew Cellar中所有以“python”开头的目录链接到/.pyenv/versions/目录下(注意使用“/python*”匹配任何以“python”开头的Cellar目录,并使用/*连接子目录)。这样避免了特别处理特定版本的需要(请参见@JacobWuzHere、@WalterGR和@laike9m的评论)。 - Tony S Yu

9

[2022] Homebrew中的Python3版本现在采用python@3.x的格式,请更新Shell。

#!/bin/bash

pyenv-brew-relink() {
    rm -f "$HOME/.pyenv/versions/*-brew"
    for i in $(brew --cellar)/python* ; do
      for p in $i/*; do
        echo $p
        ln -s -f $p $HOME/.pyenv/versions/${p##/*/}-brew
      done  
    done
    pyenv rehash
}

pyenv-brew-relink


不应该是 for i in $(brew --cellar)/python@*; do(添加了 *@*),这样就不会链接其他以 python 开头的公式(例如 python-tk@3.11python-certifi)了。 - coreuter

8
一个方便的版本重新链接函数:
pyenv-brew-relink() {
  rm -f "$HOME/.pyenv/versions/*-brew"

  for i in $(brew --cellar python)/*; do
    ln -s --force $i $HOME/.pyenv/versions/${i##/*/}-brew;
  done

  for i in $(brew --cellar python@2)/*; do
    ln -s --force $i $HOME/.pyenv/versions/${i##/*/}-brew;
  done
}

1
啊,${i##/*/} 的魔力。如果有人想知道发生了什么,请参见此处 - Fanchen Bao

4
将之前的答案结合起来,形成一个实际工作的环来绑定它们的所有部分:
pyenv-brew-relink() {
    rm -f "$HOME/.pyenv/versions/*-brew"
    for i in $(brew --cellar)/python* ; do
        ln -s -f "$p" "$HOME/.pyenv/versions/${i##/*/}-brew"
    done
    pyenv rehash
}

这个对我有效。 - D-S
这个对我没用。变量p没有定义,所以符号链接命令失败了。 - Todd Vanyo

3
如果您想让pyenv的Python和homebrew的Python共存,您需要将homebrew的Python名称命名为版本之外的其他名称。否则,它们将与pyenv使用的目录名称冲突。例如,如果您想安装pyenv Python 2.7.11和homebrew Python 2.7.11,您可以执行以下操作。
for i in `ls $(brew --cellar python)/`; do 
  ln -s $(brew --cellar python)/$i $HOME/.pyenv/versions/$i-brew; 
done

for i in `ls $(brew --cellar python3)/`; do 
  ln -s $(brew --cellar python)/$i $HOME/.pyenv/versions/$i-brew; 
done

实际上,这将在$HOME/.pyenv/versions目录中创建一个以“-brew”结尾的目录,以避免与pyenv python发生冲突。


3

为了补充@johnizzo1的答案,现在python2是python@2,因此您应该将python3的for循环更改为类似以下内容:

for i in `ls $(brew --cellar python)/`; do 
  ln -s $(brew --cellar python)/$i $HOME/.pyenv/versions/$i-brew; 
done

for i in `ls $(brew --cellar python@2)/`; do 
  ln -s $(brew --cellar python@2)/$i $HOME/.pyenv/versions/$i-brew; 
done

2

如果没有指定版本,pyenv 将使用 system 作为默认版本。

当您通过 Homebrew 安装 python@3,并且 pyenv 的版本指定为 system 时,python 指向系统中的 python 2.x,而 python3 指向由 Homebrew 安装的 python@3

因此,通常情况下我们不需要手动添加版本到 pyenv。


In 2020, after `ln -s /outside/python/x.x.x ~/.pyenv/versions/x.x.x`, you need `pyenv rehash` to rehash shims.

Example: add macos system python 2.7 to pyenv

ln -s /System/Library/Frameworks/Python.framework/Versions/2.7 ~/.pyenv/versions/2.7

pyenv rehash

虽然从技术上讲这是正确的,但当您需要为项目添加多个不同版本的python3,例如3.93.10时,仍然需要将Python版本添加到pyenv中。 - justarandomguy

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