Mac下python多版本

  1. 需要安装pyenv以支持多pytohn版本环境
  2. 需要安装virtualenv以支持python包环境隔离
  3. 但pyenv提供了virtualenv的插件,所以我们直接安装插件即可
  4. 一般安装了virtualenv后会安装virtualenvwrapper简化virtualenv的操作,但是pyenv的virtualenv的插件已经做了这个工作,不再建议安装pyenv-virtualenvwrapper(具体见这里)
  5. 所以我们安装pyenv以及virtualenv的插件即可

 

安装步骤:

以下安装采用brew

1. 查找是否有pyenv包

# Teron @ TeronsMac in ~ [22:26:16]
$ brew search pyenv
==> Searching local taps...
pyenv                      pyenv-pip-migrate          pyenv-virtualenvwrapper
pyenv-ccache               pyenv-virtualenv           pyenv-which-ext
==> Searching taps on GitHub...
==> Searching blacklisted, migrated and deleted formulae...

2. 安装pyenv

# Teron @ TeronsMac in ~ [22:26:36]
$ brew install pyenv
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
angular-cli                mongoose                   shairport-sync
convox                     paket                      vim
docker-machine-parallels   povray                     xorriso
mongo-c-driver             pygobject3                 xtensor

==> Downloading https://homebrew.bintray.com/bottles/pyenv-1.1.3.sierra.bottle.t
Already downloaded: /Users/Teron/Library/Caches/Homebrew/pyenv-1.1.3.sierra.bottle.tar.gz
==> Pouring pyenv-1.1.3.sierra.bottle.tar.gz
?  /usr/local/Cellar/pyenv/1.1.3: 581 files, 2.2MB

3. brew list查看pyenv是否安装

# Teron @ TeronsMac in ~ [22:29:43]
$ brew list
autoconf		openssl			readline
brew-cask-completion	pkg-config		sqlite
gdbm			pyenv			xz
makedepend		python3

4. pyenv -v 查看已安装

# Teron @ TeronsMac in ~ [22:32:00]
$ pyenv -v
pyenv 1.1.3

# Teron @ TeronsMac in ~ [22:32:08]
$ pyenv versions
* system (set by /Users/Teron/.python-version)

5. pyenv基本命令

$ pyenv version        # 查看当前系统使用的python版本
$ pyenv versions        # 查看当前系统拥有的python版本
$ pyenv install --list: # 列出所有可以下载的python版本.
$ pyenv install 3.4.1          # 安装3.4.1,可使用-v参数查看详细输出
$ pyenv uninstall 3.4.1         # 卸载
$ pyenv local 3.4.1     # local仅对当前目录及子目录生效,告诉当前目录使用版本2.7.5,
$ pyenv global          # 告诉全局环境使用某个版本,为了不破坏系统环境,不建议使用global设置全局版本
$ pyenv rehash          # 重建环境变量,每当你增删 Python 版本或带有可执行文件的包(如 pip)以后,都应该执行一次本命令

6. 安装python2.7.13,3.6.2版本

# Teron @ TeronsMac in ~ [22:36:26] C:2
$ pyenv install 2.7.13
Downloading Python-2.7.13.tar.xz...
-> https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz
Installing Python-2.7.13...
Installed Python-2.7.13 to /Users/Teron/.pyenv/versions/2.7.13


# Teron @ TeronsMac in ~ [22:38:33]
$ pyenv install 3.6.2
Installing Python-3.6.2...
Installed Python-3.6.2 to /Users/Teron/.pyenv/versions/3.6.2

# Teron @ TeronsMac in ~ [22:42:55]
$ pyenv versions
* system (set by /Users/Teron/.python-version)
  2.7.13
  3.6.2

# Teron @ TeronsMac in ~ [22:43:55]
$ pyenv rehash //Run this command after you install a new version of Python, or install a package that provides binaries.

7. 切换版本,发现没切过去,需要执行if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

# Teron @ TeronsMac in ~ [22:43:32]
$ pyenv local 2.7.13

# Teron @ TeronsMac in ~ [23:17:58]
$ python -V
Python 2.7.10

# Teron @ TeronsMac in ~ [23:20:15]
$ if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

# Teron @ TeronsMac in ~ [23:20:29]
$ python -V
Python 2.7.13

8. 需要往当前用户shell配置文件中写入以上配置,我的是zsh环境,则在.zshrc文件最后写入

if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

pyenv的魔法能够实现是因为它实际上重定义了你的Python命令:

$ which python
/Users/Teron/.pyenv/shims/python

当你尝试运行Python的时候,它首先查看当前目录下的.python-version目录来决定到底哪个版本的Python该运行。如果它没有发现这个文件,那么它之后回继续查找用户级别的文件~/.pyenv/version。

 

9. 安装pyenv-virtualenv

# Teron @ TeronsMac in ~ [23:23:49]
$ brew install pyenv-virtualenv
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
ruby-build                               streamlink

==> Downloading https://github.com/yyuu/pyenv-virtualenv/archive/v1.1.0.tar.gz
Already downloaded: /Users/Teron/Library/Caches/Homebrew/pyenv-virtualenv-1.1.0.tar.gz
==> ./install.sh
==> Caveats
To enable auto-activation add to your profile:
  if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
==> Summary
?  /usr/local/Cellar/pyenv-virtualenv/1.1.0: 20 files, 60.2KB, built in 1 second

# Teron @ TeronsMac in ~ [23:24:31]
$ brew list
autoconf		openssl			python3
brew-cask-completion	pkg-config		readline
gdbm			pyenv			sqlite
makedepend		pyenv-virtualenv	xz

10. 安装完同时也要在.zshrc中加入如下内容

if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi

11. pyenv-virtualenv usage

pyenv virtualenv 2.7.13 env-test:创建名为env-test的虚拟环境,对应的版本为2.7.13
pyenv activate env-test:切换到env-test虚拟环境
pyenv deactivate:退回系统环境

# Teron @ TeronsMac in ~ [23:28:10]
$ pyenv virtualenv 2.7.13 env-test
Collecting virtualenv
  Using cached virtualenv-15.1.0-py2.py3-none-any.whl
Installing collected packages: virtualenv
Successfully installed virtualenv-15.1.0
New python executable in /Users/Teron/.pyenv/versions/2.7.13/envs/env-test/bin/python2.7
Also creating executable in /Users/Teron/.pyenv/versions/2.7.13/envs/env-test/bin/python
Installing setuptools, pip, wheel...done.
Requirement already satisfied: setuptools in /Users/Teron/.pyenv/versions/2.7.13/envs/env-test/lib/python2.7/site-packages
Requirement already satisfied: pip in /Users/Teron/.pyenv/versions/2.7.13/envs/env-test/lib/python2.7/site-packages

# Teron @ TeronsMac in ~ [23:31:23]
$ pyenv versions
  system
  2.7.13
  2.7.13/envs/env-test
* 3.6.2 (set by /Users/Teron/.python-version)
  env-test

#### 后面的 set by /Users/Teron/.python-version意思指:
#### 我当前目录是/Users/Teron/,pyenv设置版本时,实际上是在当前目录创建.python-version文件记录版本; 

$ cat .python-version
3.6.2


# Teron @ TeronsMac in ~ [23:31:34]
$ pyenv activate env-test

Failed to activate virtualenv.

Perhaps pyenv-virtualenv has not been loaded into your shell properly.
Please restart current shell and try again.

# 按要求重启终端窗口ok了

# Teron @ TeronsMac in ~ [23:32:47]
$ pyenv activate env-test
pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
(env-test)

# Teron @ TeronsMac in ~ [23:32:50]
$ pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
pip (9.0.1)
setuptools (36.4.0)
wheel (0.30.0)
(env-test)
# Teron @ TeronsMac in ~ [23:33:53]
$ pip install requests
Collecting requests
  Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x10bffbb90>: Failed to establish a new connection: [Errno 65] No route to host',)': /simple/requests/
  Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 104kB/s
Collecting certifi>=2017.4.17 (from requests)
  Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB)
    100% |████████████████████████████████| 358kB 54kB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 48kB/s
Collecting idna<2.7,>=2.5 (from requests)
  Downloading idna-2.6-py2.py3-none-any.whl (56kB)
    100% |████████████████████████████████| 61kB 30kB/s
Collecting urllib3<1.23,>=1.21.1 (from requests)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 18kB/s
Installing collected packages: certifi, chardet, idna, urllib3, requests
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.6 requests-2.18.4 urllib3-1.22
(env-test)
# Teron @ TeronsMac in ~ [23:34:44]
$ pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
certifi (2017.7.27.1)
chardet (3.0.4)
idna (2.6)
pip (9.0.1)
requests (2.18.4)
setuptools (36.4.0)
urllib3 (1.22)
wheel (0.30.0)
(env-test)

# Teron @ TeronsMac in ~ [23:35:04]
$ pyenv deactivate

# Teron @ TeronsMac in ~ [23:35:35]
$ pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
pip (9.0.1)
setuptools (28.8.0)

# deactivate 后,pip list看不到env-test里安装的requests,环境隔离了

12. 列出所有的virtual环境,以及删除某个环境

# Teron @ TeronsMac in ~ [23:35:39]
$ pyenv virtualenvs
  2.7.13/envs/env-test (created from /Users/Teron/.pyenv/versions/2.7.13)
  env-test (created from /Users/Teron/.pyenv/versions/2.7.13)

# Teron @ TeronsMac in ~ [23:37:59]
$ pyenv uninstall env-test
pyenv-virtualenv: remove /Users/Teron/.pyenv/versions/2.7.13/envs/env-test? y

# Teron @ TeronsMac in ~ [23:39:01]
$ pyenv virtualenvs

# 可见刚才的env-test环境已经没了

# Teron @ TeronsMac in ~ [23:39:18]
$ pyenv versions
  system
  2.7.13
* 3.6.2 (set by /Users/Teron/.python-version)

 

以下是针对各个易混淆的概念做的说明

PyPI packages not in the standard library:

  • virtualenvIt works by installing a bunch of files in a directory (eg: env/), and then modifying the PATHenvironment variable to prefix it with a custom bin directory (eg: env/bin/). An exact copy of the python or python3 binary is placed in this directory, but Python is programmed to look for libraries relative to its path first, in the environment directory. It's not part of Python's standard library, but is officially blessed by the PyPA (Python Packaging Authority). Once activated, you can install packages in the virtual environment using pip.
  • pyenv is used to isolate Python versions. For example, you may want to test your code against Python 2.6, 2.7, 3.3, 3.4 and 3.5, so you'll need a way to switch between them. Once activated, it prefixes the PATH environment variable with ~/.pyenv/shims, where there are special files matching the Python commands (python, pip). These are not copies of the Python-shipped commands; they are special scripts that decide on the fly which version of Python to run based on the PYENV_VERSION environment variable, or the .python-versionfile, or the ~/.pyenv/version file. pyenv also makes the process of downloading and installing multiple Python versions easier, using the command pyenv install.
  • pyenv-virtualenv is a plugin for pyenv by the same author as pyenv, to allow you to use pyenv and virtualenv at the same time conveniently. However, if you're using Python 3.3 or later, pyenv-virtualenv will try to run python -m venv if it is available, instead of virtualenv. You can use virtualenv and pyenv together without pyenv-virtualenv, if you don't want the convenience features.
  • virtualenvwrapper is a set of extensions to virtualenv (see docs). It gives you commands like mkvirtualenv, lssitepackages, and especially workon for switching between different virtualenv directories. This tool is especially useful if you want multiple virtualenv directories.
  • pyenv-virtualenvwrapper is a plugin for pyenv by the same author as pyenv, to conveniently integrate virtualenvwrapper into pyenv.
  • pipenv, by Kenneth Reitz (the author of requests), is a brand new (possibly experimental) project that aims to combine Pipfile, pip and virtualenv into one command on the command-line.

Standard library:

  • pyvenv is a script shipped with Python 3 but deprecated in Python 3.6 as it had problems (not to mention the confusing name). In Python 3.6+, the exact equivalent is python3 -m venv.
  • venv is a package shipped with Python 3, which you can run using python3 -m venv(although for some reason some distros separate it out into a separate distro package, such as python3-venv on Ubuntu/Debian). It serves a similar purpose to virtualenv, and works in a very similar way, but it doesn't need to copy Python binaries around (except on Windows). Use this if you don't need to support Python 2. At the time of writing, the Python community seems to be happy with virtualenv and I haven't heard much talk of venv.