最近同时看两本书,都是关于如何利用python做数据分析的。
两本书对应两种业务场景,因此分别对应着两个不同的开发环境(其实是对应不同的发行版本)。这就很麻烦了:
- 不同环境下冲突起来没完没了,一个不小心,就要重装系统了。Mac OS 怎么重装都是个问题。
- 日常的中文语境里,没有“环境”这个概念,理解起来很恶心。
- 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环境管理工具好处:
- 隔离项目之间的第三方包依赖
- 在没有权限的情况下安装新的Python软件包
- 部署应用时,把开发环境的虚拟环境打包到生产环境
通过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 版本为的环境, 环境叫做。
pyenv virtualenv <python_version> <envname>
激活这个环境,此时 Python 版本自动变为(默认为当前shell的版本), 且是独立环境。命令中的 必须是通过pyenv安装好的python版本, 否则会出错。这个环境的真实目录位于:~/.pyenv/versions
激活虚拟环境:
pyenv activate <envname>
启用虚拟环境之后,命令行提示符将以虚拟环境名为前缀,显示:
<envname> <basic_info> $
提示符前面的就是该环境已被激活的标志。这样你就可以在这个虚拟环境下进行工作了。也可以通过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
我们再回头看下 目录的结构,其下面的bin目录中有 python.exe pip.exe这些程序,在虚拟环境已激活的情况下,你调用 python或者 pip都是调用的此目录中的程序。此时系统中的 python.exe 被 virtualenv 通过设置环境变量隐藏了起来。而 Lib目录下就是存放各种新安装的库。其中Lib//site-packages包含了下面的库。默认情况下,虚拟环境会依赖系统环境中的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版本的环境
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 | |
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多版本切换工具-Pyenvvirtualenv及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