这是一篇旧文,编写于2017年,用于公司内部交流。整理更新后于2019年04月06日重发,内容有效期乐观估计半年,阅读请注意保质期。
为什么用python虚拟环境
python版本差异
python当前主要有2个release版本 Python 2.7.16 和 Python 3.7.3 ,这两个版本在一些语法上存在较大差异。
如果你从网上下载了一段python代码,却运行不起来,首先要排除的是python版本问题。比如下面这个 hello_python.py ,代码非常简单,就一句打印 hello,world
到屏幕上。
print "hello,world"复制代码
如果你使用python2.7,恭喜你可以很好的跑起来,如下:
(python27) ➜ python hello_python.pyhello,world复制代码
如果你使用的是python3,可能就实现从入门到放弃:(
(python37) ➜ python hello_python.py File "hello_python.py", line 3 print "hello,world" ^SyntaxError: Missing parentheses in call to 'print'. Did you mean print("hello,world")?复制代码
python3 中让代码正常运行的办法和提示一样,修改语句为
print("hello,world")
python2.7已经 “过时”,pip运行是会提示:
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.复制代码
现实状况却是一些库的版本问题或者历史遗留问题,可能需要在python2和python3之间切换。
python使用场景差异
python语言应用非常广泛,涉及服务器脚本、爬虫、程序开发、科学计算,大数据,机器学习等。不同的场景下,使用的库是有差异:
使用场景 | 常用库 |
---|---|
程序开发 | flask/django |
爬虫 | requests/beautifulsoup4/scrapy |
科学计算 | pandas/numpy/matplotlib |
... | ... |
库又会依赖另外的库,这样如果全部安装在一个环境里,难以规避库的版本冲突。
鉴于python版本差异和使用场景差异,推荐使用虚拟环境进行隔离管理,省事不少。
怎么使用虚拟环境
使用 pip
使用虚拟环境之前,我们先花一点点时间来了解python的包安装工具 pip , 相信我这很简单。
Python的最大的优势之一是丰富的库,跨平台,在UNIX,Windows和Macintosh兼容很好。
安装这些库,让开发速度飚起来,就需要使用 pip。
下面使用pip
安装requests
库示例:
(py27studio) ➜ pytest pip install requestsLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simpleCollecting requests Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f1/ca/10332a30cb25b627192b4ea272c351bce3ca1091e541245cccbace6051d8/requests-2.20.0-py2.py3-none-any.whl (60kB) 100% |████████████████████████████████| 61kB 1.5MB/sCollecting chardet<3.1.0,>=3.0.2 (from requests) Using cached https://pypi.tuna.tsinghua.edu.cn/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whlCollecting urllib3<1.25,>=1.21.1 (from requests) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl (118kB) 100% |████████████████████████████████| 122kB 1.5MB/sCollecting certifi>=2017.4.17 (from requests) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/56/9d/1d02dd80bc4cd955f98980f28c5ee2200e1209292d5f9e9cc8d030d18655/certifi-2018.10.15-py2.py3-none-any.whl (146kB) 100% |████████████████████████████████| 153kB 287kB/sCollecting idna<2.8,>=2.5 (from requests) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/4b/2a/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165/idna-2.7-py2.py3-none-any.whl (58kB) 100% |████████████████████████████████| 61kB 131kB/sInstalling collected packages: chardet, urllib3, certifi, idna, requestsSuccessfully installed certifi-2018.10.15 chardet-3.0.4 idna-2.7 requests-2.20.0 urllib3-1.24.1复制代码
从示例可见 pip 的2个特点:
-
快速安装。命令行中一键安装完成。
-
自动解决依赖。在安装requests的同时还安装了: chardet, urllib3, certifi, idna 并且自动解决各个库的版本问题, 一般情况下我们不用关心这些细节。
下面是 pip的一些常用命令
# 列出库列表pip list# 升级pippip install pip -U# 安装指定的库pip install name# 删除指定的库 pip uninstall name复制代码
了解 pip 的常用命令后,可以愉快的写代码了。逐渐你会遇到在不同机器上同步库或者同事使用你的代码,需要安装相同的库。这时候你就需要pip的2个进阶命令了。
# 将当期环境中的库列表形成 requirements.txt 文件pip freeze >requirements.txt# 根据 requirements.txt 批量安装库pip install -r requirements.txt复制代码
你可以使用下面2个命令,获取pip的使用帮助,了解更多
pip helppip install -h复制代码
由于PyPI服务位于国外,访问起来比较缓慢,可以使用国内的一些源进行加速
设置pip使用国内源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple复制代码
一些其它的源: 豆瓣源: 阿里云源:
其它平台/语言也有类似的解决方案,如果你有兴趣可以使用下面关键字自行了解。
yum/apt/npm/brew/maven...
使用 venv
Python 从3.3 版本开始,自带了一个虚拟环境 venv,在 中可以看到它的详细介绍。
在 *nix 系统上,可以直接执行 pyvenv ./blog-env
来创建一个虚拟环境。在 Windows 系统上,则可以使用 python -m venv ./blog-env
来创建, 这个命令也可以用于 *nix 系统,推荐使用。
venv创建的虚拟环境,建议就在项目目录,这样使用起来更方便,没有记忆负担。
创建完成后 *nix 系统上, 使用 source ./blog-env/bin/activate
进入虚拟环境,window系统上,使用 Scripts\\activate.bat
,效果如下:
➜ blog source ./blog-env/bin/activate(blog-env) ➜ blog复制代码
注意在命令提示符之前新出现的 (blog-env) 标识进入了新的虚拟环境。
这样很方便就获得了一个隔离的python环境。
使用 pipenv
pipenv是Kenneth Reitz推出的python包依赖工具, kr就是大名鼎鼎requests的作者。pipenv号称Python Dev Workflow for Humans, 实力可见一斑。
介绍pipenv之前,我们先看venv存在的问题。我这里有一个django项目,使用django-rest-framework提供RestFul api服务, 利用jwt进行前后端认证,项目安装完后依赖大概如下:
(wxsc) ➜ wordpress pip listPackage Version----------------------- ----------asn1crypto 0.24.0certifi 2018.10.15cffi 1.11.5chardet 3.0.4coreapi 2.3.3coreschema 0.0.4cryptography 2.3.1diff-match-patch 20181111Django 2.0.5django-crispy-forms 1.7.2django-filter 2.0.0django-formtools 2.1django-import-export 1.1.0django-reversion 3.0.0djangorestframework 3.9.0djangorestframework-jwt 1.11.0et-xmlfile 1.0.1future 0.16.0httpie 1.0.0httplib2 0.12.0idna 2.7itypes 1.1.0jdcal 1.4Jinja2 2.10Markdown 3.0.1MarkupSafe 1.1.0odfpy 1.3.6openpyxl 2.5.10pip 18.1pipenv 2018.11.14pycparser 2.19Pygments 2.2.0PyJWT 1.6.4PyMySQL 0.9.2pytz 2018.5PyYAML 3.13requests 2.20.1setuptools 40.6.2six 1.11.0tablib 0.12.1unicodecsv 0.14.1uritemplate 3.0.0urllib3 1.24.1virtualenv 16.1.0virtualenv-clone 0.4.0wheel 0.32.2xlrd 1.1.0XlsxWriter 1.1.2xlwt 1.3.0复制代码
前前后后大约安装了50个包,最后完全不清楚,那些是我直接安装的,那些是间接安装的,pipenv可以解决这个问题。
pipenv 安装很方便:
$ pip install pipenv复制代码
如果标准版本还是python2.7,则可以使用 pip3 install pipenv
pipenv使用起来也很方便。接下来我们一起了解这个过程。
创建一个新的工作目录myproject
,使用下面命令创建虚拟环境,创建完成后目录下会生成一个Pipfile文件。
$ pipenv --threeCreating a virtualenv for this project…Pipfile: /private/tmp/myproject/PipfileUsing /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 (3.7.1) to create virtualenv…✔ CompleteUsing base prefix '/Library/Frameworks/Python.framework/Versions/3.7'New python executable in /Users/tu/codes/venv/myproject-7Ev2diGY/bin/python3Also creating executable in /Users/tu/codes/venv/myproject-7Ev2diGY/bin/pythonInstalling setuptools, pip, wheel...done.Running virtualenv with interpreter /Library/Frameworks/Python.framework/Versions/3.7/bin/python3Virtualenv location: /Users/tu/codes/venv/myproject-7Ev2diGYCreating a Pipfile for this project…复制代码
查看虚拟环境的实际目录,了解python命令路径(可以用于配合pycharm选择解释器)。
$ pipenv --venv$ pipenv --py复制代码
pipenv 的虚拟环境会统一存放,不会在项目路径下
安装软件包。包安装完成后,会在项目路径下生成Pipfile.lock文件。
$ pipenv install requests$ pipenv install django复制代码
注意: 这里不是使用 pip 进行包安装,而是使用 pipenv 。
查看项目依赖。视图比较清晰的描述了,项目依赖了2个包,每个包又分别依赖了其它的一些包。
➜ myproject2 pipenv graphDjango==2.1.3 - pytz [required: Any, installed: 2018.7]requests==2.20.1 - certifi [required: >=2017.4.17, installed: 2018.10.15] - chardet [required: >=3.0.2,<3.1.0, installed: 3.0.4] - idna [required: >=2.5,<2.8, installed: 2.7] - urllib3 [required: >=1.21.1,<1.25, installed: 1.24.1]复制代码
重用requirements.txt
文件。在项目目录下创建requirements.txt
,内容参见上文。
$ pipenv install复制代码
pipenv 默认会读取本地目录,也可以使用**-r**参数指定
requirements.txt
位置。
pipenv 的依赖和 venv 有差异,可能直接导入 venv中的
requirements.txt
有一些问题,可以直接手工安装。
pipenv就简单介绍到这里,大家可以看。总的来说venv和pipenv各有优势吧,venv原生自带,简单方便,比较适合服务器上调试;pipenv,功能强大更适合本地调试。
Anaconda
科学计算领域,python著名的库pandas,numpy和matplotlib, 然后还有图像处理和视觉这块的opencv,以及机器学习的tensorflow安装比较复杂,在这个领域一般使用anaconda的解决方案,其wiki介绍如下:
Anaconda 是一种Python语言的免费增值开源发行版,用于进行大规模数据处理、预测分析,和科学计算,致力于简化包的管理和部署。 Anaconda使用软件包管理系统Conda进行包管理。
我选择的是anaconda3,使用的iterm2,安装完成后会有路径问题,需要在~/.zshrc
中添加:
export PATH="/anaconda3/bin:$PATH"复制代码
然后访问使用下面命令查看anaconda环境。
➜ ~ which conda/anaconda3/bin/conda➜ ~ conda --versionconda 4.5.11复制代码
创建虚拟环境,并进入虚拟环境:
conda create --name python36 python=3.6➜ ~ source activate python36(python36) ➜ ~(python36) ➜ ~ python -VPython 3.6.7 :: Anaconda, Inc.(python36) ➜ ~ source deactivate➜ ~复制代码
查看conda管理的环境列表:
➜ ~ conda info -e# conda environments:#base * /anaconda3python36 /anaconda3/envs/python36复制代码
Anaconda在个人研发过程中使用不多,如果想了解更多,可以看。
docker时代的python环境
前面介绍的内容,都是在本地进行一些配置,创建各种环境。可是本地就一个,折腾几次后还是容易乱,docker这么强大,我们也可以用docker来玩python开发。
首先,我们编写hello.py
,代码如下:
# -*- coding:utf-8 -*-def test(): print "Hello, python, docker"if __name__ == "__main__": test()复制代码
然后执行下面命令:
docker run -it --rm --name docker-python2 -v "$PWD":/usr/src/myapp -w /usr/src/myapp python:2.7.16-alpine3.9 python hello.py复制代码
命令结果如下:
Unable to find image 'python:2.7.16-alpine3.9' locally2.7.16-alpine3.9: Pulling from library/python8e402f1a9c57: Already existsd8cdc394c05b: Pull complete1e2b4a75cc6b: Pull complete2fbbf60d928e: Pull completeDigest: sha256:46d6e67d464a2811efe60440248623b14cb6db273fac59631dd8bd9e13a77491Status: Downloaded newer image for python:2.7.16-alpine3.9Hello, python, docker复制代码
注意,初次执行会进行镜像文件下载,比较缓慢,下载成功后再次执行脚本就会非常迅速了。
这里的docker命令比较复杂,可以先不用管它的含义。我们继续编写hello3.py
,代码如下:
# -*- coding:utf-8 -*-def test(): print("Hello, python, docker")if __name__ == "__main__": test()复制代码
使用下面命令执行:
docker run -it --rm --name docker-python3 -v "$PWD":/usr/src/myapp -w /usr/src/myapp python:3.7.3-alpine3.9 python hello3.py复制代码
执行结果如下:
Unable to find image 'python:3.7.3-alpine3.9' locally3.7.3-alpine3.9: Pulling from library/pythonDigest: sha256:11568bb68bd375727e468ea5995f556139ff305eed9d8ee1d04b1a4a03a6486aStatus: Downloaded newer image for python:3.7.3-alpine3.9Hello, python, docker复制代码
我们简单了解一下运行命令的含义:
➜ python docker run --helpUsage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] -i, --interactive Keep STDIN open even if not attached ... --rm Automatically remove the container when it exits ... -t, --tty Allocate a pseudo-TTY ... -v, --volume list Bind mount a volume --volume-driver string Optional volume driver for the container --volumes-from list Mount volumes from the specified container(s) -w, --workdir string Working directory inside the container复制代码
docker run -it --rm --name docker-python2 -v "$PWD":/usr/src/myapp -w /usr/src/myapp python:2.7.16-alpine3.9 python hello.py
翻译过来的意思大概是下面几点:
- 使用 python:2.7.16-alpine3.9 镜像启动容器,python表示镜像名称,2.7.16-alpine3.9表示版本标签。
- 容器名称命名为docker-python2,并且输出信息到当前终端,容器运行完成后自动删除。
- 容器使用数据卷,将当前目录和容器内的
/usr/src/myapp
目录进行映射。 - 设置
/usr/src/myapp
为工作目录,然后运行python hello.py
命令。
这样经过上面几步,我们就使用docker容器执行了hello.py
了。而且我们也有了2个镜像,可以分别执行python2和python3的代码。当然实际的工程中,只是执行一个py文件 有点杀鸡用牛刀的感觉,可以如果执行一个django项目,却是可以很好的保持开发环境和部署环境的一致。这部分内容,以后我会进行补充介绍。
提示:docker和venv/pipenv也可以配合使用,将虚拟环境创建在当前目录即可,留给大家动手探索吧。
回顾
最后,我们一起来简单回顾一下python虚拟环境:
- 使用python虚拟环境可以有效解决python语法版本差异及使用场景差异。
- 使用pip安装各种包。
- python3自带venv创建和管理各种环境。
- pipenv是一种混合了pip和venv的环境管理方法。
- 使用anaconda管理python科学计算环境。
- 可以使用docker等方式使用python环境。
附录
如果继续使用pyhon2,可以参靠下面部分内容。python2的虚拟环境 virtualenv&virtualenvwrapper。
virtualenv 是一个创建隔绝的Python环境的工具,可以创建一个包含所有必要的可执行文件的文件夹,用来使用Python工程所需的包。
virtualenv安装非常简单,直接使用下面命令:
pip install virtualenv复制代码
可能会遇到权限问题,可以使用sudo提权
但是virtualenv有一个弊端是,每次会在当前目录创建venv)(pycharm默认使用这种方式),每次需要自己记住不同的虚拟机目录,使用起来不太方便。 这里我们直接跳过virtualenv的使用,继续使用其扩展包virtualenvwrapper
virtualenvwrapper安装也非常简单,直接使用下面命令:
pip install virtualenvwrapper复制代码
! 注意:windows用户使用的命令是 pip install virtualenvwrapper-win 后面带**-win**
使用virtualenvwrapper需要先设置环境变量,我使用的iTerm2
配置的zshrc
,需要在用户根目录下的.zshrc
中增加下面2行:
export WORKON_HOME=~/codes/venvsource /usr/local/bin/virtualenvwrapper.sh复制代码
配置好环境变量后,退出重启term
生效。
创建一个flask开发环境
mkvirtualenv flaskUsing base prefix '/Library/Frameworks/Python.framework/Versions/2.7'New python executable in /Users/tu/codes/venv/flask/bin/pythonAlso creating executable in /Users/tu/codes/venv/flask/bin/pythonInstalling setuptools, pip, wheel...done.virtualenvwrapper.user_scripts creating /Users/tu/codes/venv/flask/bin/predeactivatevirtualenvwrapper.user_scripts creating /Users/tu/codes/venv/flask/bin/postdeactivatevirtualenvwrapper.user_scripts creating /Users/tu/codes/venv/flask/bin/preactivatevirtualenvwrapper.user_scripts creating /Users/tu/codes/venv/flask/bin/postactivatevirtualenvwrapper.user_scripts creating /Users/tu/codes/venv/flask/bin/get_env_details(flask) ➜ pytest复制代码
注意创建好虚拟环境后会自动进入该环境,命令提示符前会显示当前环境的名称,例如(flask) 字样。
再创建一个爬虫的开发环境
mkvirtualenv spider...复制代码
这样你可以在flask的环境中安装flask库,spider的环境中安装requests库,而不用担心依赖冲突。
如果你希望创建一个python3版本的环境,需要先行安装好python3,然后使用下面命令:
# -p 参数指定版本,可以使用python3的绝对路径mkvirtualenv py3studio -p python3复制代码
其它常用命令,如下:
# 列出env列表workon# 进入指定的envworkon name# 退出当前envdeactivate# 删除envrmvirtualenv name复制代码
ok,我们使用pip安装virtualenv和virtualenvwrapper,顺利的解决了不同版本的python问题,可以愉快的开发(玩耍)了。