×

Python环境Memo

96
Nora_Jianshu
2016.06.20 22:35* 字数 3425

最近同时看两本书,都是关于如何利用python做数据分析的。
两本书对应两种业务场景,因此分别对应着两个不同的开发环境(其实是对应不同的发行版本)。这就很麻烦了:

  1. 不同环境下冲突起来没完没了,一个不小心,就要重装系统了。Mac OS 怎么重装都是个问题。
  2. 日常的中文语境里,没有“环境”这个概念,理解起来很恶心。
  3. Google里,对环境的定义也不够清晰。
    简单写一下这两天Google来理解,也没辜负这些tabs :)


    解决一个问题前不关闭tab的习惯

什么是发行版本?

Bundle。
发行版本是一个Bundle,里面会对不同库的不同版本进行“捆绑”。
以软件和系统为例,不同的软件的rc、beta版本就是不同的发行版本。“雨枫木林”,“番茄花园”就是windows的不同发行版本。
不同python发行版本简介

环境

一般而言,一个“环境”就是相互依赖的不同版本的不同库之间的“捆版”。同一个库只有一个版本。

版本环境

一般安装的发行版本有canopy,anaconda,sage,pythonxy。系统也会自带有python。每一个发行版本对应的环境可以称为“版本环境”。根据不同的项目,会有不同版本的部署需求,而系统自带的python版本会影响很多软件(绝大多数系统工具依赖系统Python),合理的版本环境管理就很必要了。

虚拟环境

虚拟环境意味着和系统(默认)环境分离的独立环境。通过与系统环境以及其他Python环境隔离, 避免干扰。

显然,版本环境是虚拟环境的一种。

OS X寻找环境的方式

OS X通过directory找到目标版本的安装地址,不同版本的directory是在系统环境变量($PATH)里声明的。当$PATH中有多个版本信息时,查询的逻辑类似“栈”,最近写入的最先调用。
PS:不同编译程序都需要到$PATH查找自身对应的环境变量,如ruby,perl,java等。

<$PATH>** -->** <python_version>

Bash(默认Shell)有不同的步骤初始化环境变量。
Mac下具体环境变量调用顺序:
Mac OS X环境变量相关
MAC 设置环境变量path的几种方法
Mac OS X 环境变量设置【转】

一个常见的环境冲突例子

默认的python是canopy,因为其他需求,需要安装anaconda。安装后,bash优先调用anaconda,因为python的升级很多时候是不考虑前向兼容的,容易莫名其妙出现一些之前从未出现的报错或警告。

pyenv管理版本环境

pyenv 是一个允许多个Python解释器版本同时安装于一台机器的工具。这解决了不同的项目需要不同版本的Python的问题。比如,为了兼容性,可以很容易地为一个项目安装Python 2.7,而继续使用Python 3.4作为默认的编辑器。pyenv不止限于CPython版本——它还能安装PyPy、anaconda、miniconda、stackless、jython和ironpython解释器。
pyenv的工作原理是在一个叫做 shims目录中创建Python解释器(以及其他工具像 pip和 2to3等)的假版本。当系统寻找名为 python的应用时,它会先在 shims目录中查找,并使用那个假版本,然后会传递命令到pyenv中。pyenv基于环境变量(shell)、 .python-version文件(local)和全局默认设置(global)的信息就知道该运行哪个版本的Python。

PYENV_VERSION-->.python-version--><$PATH>-->.pyenv/shims--><python_version>

pyenv-virtualenv插件管理虚拟环境

pyenv不是管理虚拟环境的工具,但是有一个叫做 pyenv-virtualenv 的插件可以自动化不同环境的创建,而且也能够使用现有的pyenv工具,基于环境变量或者 .python-version文件,来切换不同的环境。(和virtualenv的作用一样)

pyenv环境管理工具好处:

  1. 隔离项目之间的第三方包依赖
  2. 在没有权限的情况下安装新的Python软件包
  3. 部署应用时,把开发环境的虚拟环境打包到生产环境

通过pyenv安装的环境才能通过这个工具进行环境管理。部分情况下,某些发行版本通过Homebrew和pyenv都可以安装(如anaconda),然而用Homebrew安装方式将无法通过pyenv管理新安装环境。(根据 ~/.pyenv/versions判断)。同时也不应该使用Homebrew在虚拟环境下安装不同软件的库,因为Homebrew会忽略虚拟环境的安装需求,安装到Homebrew的默认directory下。

其他

常用命令

pyenv命令

利用pyenv命令安装的python版本都安装在~/.pyenv/versions文件夹下。
已经安装的python版本

pyenv versions

当前使用的版本

pyenv version

我们可以查看一下可安装的python版本

pyenv install -l

选好要安装的版本后,运行下面这条命令安装(.pyenv/cache用于缓存公用的package)

pyenv install <python_version>

安装完成之后需要对数据库进行更新:

pyenv rehash

我们可以用pyenv versions查看已安装的版本,要切换python版本,可以用

pyenv global/local <python_version>

运行global命令会切换全局(系统默认)的python版本;而local命令则会在当前目录下创建.python_version,管理当前目录及其子目录(子目录有.python_version的情况下)的python版本。(需要cd到目标文件夹)

设置本次shell中临时执行的python版本

pyenv shell <python_version>

卸载(删除)已安装的python版本

pyenv uninstall <python_version>

pyenv-virtuallenv命令

创建一个 Python 版本为<python_version>的环境, 环境叫做<envname>。

pyenv virtualenv <python_version> <envname>

激活<envname>这个环境,此时 Python 版本自动变为<python_version>(默认为当前shell的版本), 且是独立环境。命令中的 <python_version>必须是通过pyenv安装好的python版本, 否则会出错。这个环境的真实目录位于:~/.pyenv/versions

激活虚拟环境:

pyenv activate <envname>

启用虚拟环境之后,命令行提示符将以虚拟环境名为前缀,显示:

<envname> <basic_info> $

提示符前面的<envname>就是该环境已被激活的标志。这样你就可以在这个虚拟环境下进行工作了。也可以通过python打印出os.sys.path进行验证,同时,执行 pip help,你可以看到 pip freeze是输出当前 Python 环境下已经安装的所有第三方库。

Python 3.5.1 |Continuum Analytics, Inc.| (default, Dec 7 2015, 11:24:55)
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>>** print(os.sys.path)**
['', '/Users/NoraChan/.pyenv/versions/test/lib/python35.zip', '/Users/NoraChan/.pyenv/versions/test/lib/python3.5', '/Users/NoraChan/.pyenv/versions/test/lib/python3.5/plat-darwin', '/Users/NoraChan/.pyenv/versions/test/lib/python3.5/lib-dynload', '/Users/NoraChan/.pyenv/versions/test/lib/python3.5/site-packages', '/Users/NoraChan/.pyenv/versions/test/lib/python3.5/site-packages/setuptools-23.0.0-py3.5.egg']

离开已经激活的环境:

pyenv deactivate

我们再回头看下 <envname>目录的结构,其下面的bin目录中有 python.exe pip.exe这些程序,在虚拟环境已激活的情况下,你调用 python或者 pip都是调用的此目录中的程序。此时系统中的 python.exe 被 virtualenv 通过设置环境变量隐藏了起来。而 Lib目录下就是存放各种新安装的库。其中Lib/<python_version>/site-packages包含了<python_version>下面的库。默认情况下,虚拟环境会依赖系统环境中的site packages,就是说系统中已经安装好的第三方package也会安装在虚拟环境中,如果不想依赖这些package,那么可以加上参数 --no-site-packages建立虚拟环境。

--distribute参数将会自动在虚拟环境中安装pip,免去了手动安装的麻烦。
--no-site-packages参数是在创建此虚拟环境中不从系统 Python 中把已经安装了的库也安装到这里来,所以这里是一个干净的新 Python 环境。你可以在这里调用 pip或者 easy_install来安装各种你需要的库到这个环境中来,而不会影响到你系统中 Python 的情况,所以说它是一个虚拟的Python 环境。

从os.sys.path中可以看出,这个环境下执行python相关的操作都是限定在虚拟环境中。

# Showing only files/directories relevant to the discussion at hand
.
|-- bin
| |-- activate # <-- Activates this virtualenv
| |-- pip # <-- pip specific to this virtualenv
| `-- python # <-- A copy of python interpreter
`-- lib
`-- python3.5 # <-- This is where all new packages will go

conda命令

conda也是一个环境工具,本质是利用pyenv进行环境管理。
使用conda让两个不同的版本并行运行。
对于python3.4版本:

conda create -n py3 python=3.4 anaconda
source activate py3

对于python2.7版本:

conda create -n py2 python=2.7 anaconda
source activate py2

这样就会在Anaconda安装目录下的envs目录下创建py2这个目录。
向其中安装扩展可以直接用conda install并用-n指明安装到的环境,这里自然就是py2。像virtualenv那样,先activate,然后在虚拟环境中安装。

管理package####

conda update <package-name>
condo install <package-name>=x.x #安装包,指定包的版本

conda和pip关联的很好。使用pip安装的东西可以使用conda来管理

针对特定环境安装特定版本的库

activate虚拟环境(conda/pyenv-virtualenv)然后在虚拟环境中安装。
Canopy&Python3.x的环境管理工具

可以测试多个python版本的环境

tox工具

Homebrew安装pyenv

安装pyenv有多种方式,Homebrew是其中一种。这种方式是不修改系统环境变量的。因此Homebrew不会破坏OS X 原生的环境。同时它安装的所有文件都是在用户独立空间内的,这让你安装的所有软件对于该用户来说都是可以访问的,不需要使用sudo命令。

Homebrew安装pyenv的警告:
1.使用Homebrew的目录:

==> Caveats
To use Homebrew's directories rather than ~/.pyenv add to your profile:
export PYENV_ROOT=/usr/local/var/pyenv

这里的意思在profile里执行,用于bash里初始化环境变量:

echo 'PYENV_ROOT=/usr/local/var/pyenv' >>~/.bash_profile

目前建议不要这样子做,用Homebrew的目录并没有好处,而且容易产生问题。

2.激活shims:

==> Caveats
To enable shims and autocompletion add to your profile:
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

不加这一行的情况下,当我们使用pyenv global 3.5.1后现在指向了3.5.1,但是当运行python version却还显示的是2.7.2

echo 'if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi' >>~/.bash_profile

pyenv Environment variables

You can affect how pyenv operates with the following settings:

name default description
PYENV_VERSION Specifies the Python version to be used.Also see pyenv shell
PYENV_ROOT ~/.pyenv Defines the directory under which Python versions and shims reside.Also see pyenv root
PYENV_DEBUG Outputs debug information.Also as: pyenv --debug <subcommand>
PYENV_HOOK_PATH see wiki Colon-separated list of paths searched for pyenv hooks.
PYENV_DIR $PWD Directory to start searching for .python-version files.

pyenv-virtualenvwrapper

pyenv-virtualenvwrapper看起来是virtualenv命令的封装?用于创建、删除、复制、切换?作为pyenv的插件,感觉没什么用。

利用非bin/python执行.py

一些bash的脚本,需在开头一行指定脚本的解释程序,如:#!/usr/bin/env python但有时候也用 #!/usr/bin/python,区别如下:
#!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器; #!/usr/bin/env python这种用法是为了防止操作系统用户没有将python装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找python的安装路径,再调用对应路径下的解释器程序完成操作。 #!/usr/bin/python相当于写死了python路径; #!/usr/bin/env python会去环境设置寻找python目录,推荐这种写法。

使用了pyenv之后会, pyenv的python在/usr/bin/python前面了。

PATH=/Users/rcf/.pyenv/shims:/Users/rcf/Soft/maven/bin:/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin

所以以后再用#!/usr/bin/python就会出现版本不匹配了。建议使用
#!/usr/bin/env python

或者

shell mv /usr/bin/python /usr/bin/python2.7.10 ln -s /usr/bin/python /Users/rcf/.pyenv/shims/python

类似工具:

版本管理工具 语言
rvm ruby
nvm node
pyenv python

其他命令

bash命令
which python
在系统环境变量中定位python的directory
pyenv which python
在shims中定位python的directory

Reference

homebrew是ruby写的OS X 下的包管理工具
Python多版本切换工具-Pyenv\virtualenv及Anaconda科学计算环境的配置
Python之包管理工具
用了pyenv-virtualenv, 天黑都不怕
Python系列(2)之pyenv进行多版本管理
一篇文章入门Python生态系统
Python Virtual Environments - a Primer
#!/usr/bin/env 脚本解释程序的作用
PEP 405 -- Python Virtual Environments
virtualenv
Openstack工程的持续集成实践1--tox

数据科学&hacker
Web note ad 1