python virtualenv
在使用virtualenv之前,可以先从这篇文章了解起来:
https://virtualenv-chinese-docs.readthedocs.io/en/latest/#
一、什么是virtualenv?
virtualenv可创建隔离的Python开发环境,用于解决依赖、版本以及间接权限,它是workingenv和vitrual-python的扩展。
(1)不同的virtualenv环境隔离,每个环境都有独立安装目录
(2)可以通过像--python的这种命令来更改解释器的版本
(3)开发可以在不同的virtualenv环境下工作、部署、测试,并且不受当前系统限制
virtualenv官网介绍:https://virtualenv.pypa.io/en/stable/
二、构建virtualenv隔离环境:
该构建操作是基于CentOS建立的,可通过搭建虚拟机实现。
S1、构建基础ENV环境,执行命令:virtualenv ENV
该操作会创建 ENV/lib/pythonX.X/site-packages 目录 和 ENV/bin/python , 前者用来存放要安装的模块,后者就是隔离环境的Python解释器。 在virtualenv环境下使用此解释器(包括以 #!/path/to/ENV/bin/python 开头的脚本)时,使用的都是隔离环境下的模块。
(此外可更改setuptools、distribute的使用)
S2、进入ENV,**ENV环境,执行命令:source bin/activate
**之后,系统的环境变量会有所改变,如下所示:
[[email protected] ENV]# echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/lanyyyy/.local/bin:/home/lanyyyy/bin
[[email protected] ENV]# source bin/activate
(ENV) [[email protected] ENV]# echo $PATH
/home/lanyyyy/workspace/ENV/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/lanyyyy/.local/bin:/home/lanyyyy/bin
可以看到,**环境会有前缀(ENV),便于你区分当前的环境使用。如果想禁用的话,在执行activate前对 VIRTUAL_ENV_DISABLE_PROMPT赋任意值即可。
S3、再构建一个ENV1环境,并且使用pip在不同的环境安装tox,可以看到:
(ENV1) [[email protected] ENV1]# pip list | grep tox
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.
tox (2.7.0) # tox的2.7.0版本
(ENV1) [[email protected] ENV1]# deactivate
[[email protected] ENV1]# cd ../ENV
[[email protected] ENV]# source bin/activate
(ENV) [[email protected] ENV]# pip list | grep tox
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.
tox (2.8.1) # tox的2.8.1版本
可以看到,不同的ENV可以使用不同的版本。
S4、最后,退出virtualenv环境:
deactivate
三、其它一些功能或参数:
(1)这里需要强调的是,在使用virtualenv命令的时候,需要加上目标路径。
(2)可以使用avtivate_this更改解释器的路径(没太理解,可能需要具体场景分析)
(3)重新定位隔离环境(也没太明白)
(4)指定不同的python解释器构建virtualenv环境:
四、virtualenvwrapper:
virtualenvwrapper是virtualenv的扩展包,用于更加方便管理虚拟环境,包括:
(1)将所有虚拟环境整合在一个目录上;
(2)管理(新增、删除、复制)虚拟环境
(3)快速切换虚拟环境
具体的使用执行方式如下:
pip install virtualenvwrapper
mkdir ~/.virtualenvs
export WORKON_HOME=~/.virtualenvs # 可以添加到~/.bashrc
source /usr/bin/virtualenvwrapper.sh # 该路径要查看环境的具体路径
查看virtualenvwrapper的命令:
[[email protected] workspace]# virtualenvwrapper --help
virtualenvwrapper is a set of extensions to Ian Bicking's virtualenv
tool. The extensions include wrappers for creating and deleting
virtual environments and otherwise managing your development workflow,
making it easier to work on more than one project at a time without
introducing conflicts in their dependencies.
For more information please refer to the documentation:
http://virtualenvwrapper.readthedocs.org/en/latest/command_ref.html
Commands available:
add2virtualenv: add directory to the import path #
allvirtualenv: run a command in all virtualenvs # 显示所有虚环境
cdproject: change directory to the active project # 更换目录
cdsitepackages: change to the site-packages directory # 进入虚环境库目录
cdvirtualenv: change to the $VIRTUAL_ENV directory # 进入虚环境目录
cpvirtualenv: duplicate the named virtualenv to make a new one # 复制生成一个新的
lssitepackages: list contents of the site-packages directory # 显示库
lsvirtualenv: list virtualenvs # 显示虚环境
mkproject: create a new project directory and its associated virtualenv # 创建目录
mktmpenv: create a temporary virtualenv
mkvirtualenv: Create a new virtualenv in $WORKON_HOME # 创建virtualenv
rmvirtualenv: Remove a virtualenv # 删除env
setvirtualenvproject: associate a project directory with a virtualenv
showvirtualenv: show details of a single virtualenv
toggleglobalsitepackages: turn access to global site-packages on/off
virtualenvwrapper: show this help message
wipeenv: remove all packages installed in the current virtualenv
workon: list or change working virtualenvs # 显示当前工程
这些命令简化了virtualenv的使用。
其他命令比如: virtualenv-burrito、autoenv略
五、virtualenv代码解析:
S1、在执行virtualenv构建环境的时候,调用的是/usr/bin/virtualenv命令:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from virtualenv import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
S2、查看main函数的详情/usr/lib/python2.7/site-packages/virtualenv.py:
def main():
...(略)
create_environment(home_dir, # 构建环境
site_packages=options.system_site_packages,
clear=options.clear,
unzip_setuptools=options.unzip_setuptools,
prompt=options.prompt,
search_dirs=options.search_dirs,
download=options.download,
no_setuptools=options.no_setuptools,
no_pip=options.no_pip,
no_wheel=options.no_wheel,
symlink=options.symlink)
...(略)
S3、环境构建函数:create_environment():
def create_environment(home_dir, site_packages=False, clear=False,
unzip_setuptools=False,
prompt=None, search_dirs=None, download=False,
no_setuptools=False, no_pip=False, no_wheel=False,
symlink=True):
"""
Creates a new environment in ``home_dir``.
If ``site_packages`` is true, then the global ``site-packages/``
directory will be on the path.
If ``clear`` is true (default False) then the environment will
first be cleared.
"""
home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) # 构建虚环境目录
py_executable = os.path.abspath(install_python( # 构建执行函数
home_dir, lib_dir, inc_dir, bin_dir,
site_packages=site_packages, clear=clear, symlink=symlink))
install_distutils(home_dir) # 构建distutils
to_install = []
if not no_setuptools:
to_install.append('setuptools')
if not no_pip:
S4、查看**函数avtivate:
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () { # 解除activate环境
unset -f pydoc >/dev/null 2>&1
# reset old environment variables
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi
if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/lanyyyy/workspace/ENV" # 当前该环境的目录
export VIRTUAL_ENV # 导入工作目录
_OLD_VIRTUAL_PATH="$PATH" # 备份旧目录
PATH="$VIRTUAL_ENV/bin:$PATH" # 新增virtualenv目录
export PATH
# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" # 备份PYTHONHOME
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then # 虚环境提示符设置
_OLD_VIRTUAL_PS1="$PS1" # PS1为linux的提示符
if [ "x" != x ] ; then
PS1="$PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
fi
export PS1 # 更新环境提示符
fi
# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc # 这块为什么取消暂不理解?
pydoc () {
python -m pydoc "[email protected]" # 使用pydoc显示模块详情
}
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null # 清除hash记录的命令
fi
# 不使用hash清除的话,比如调用tox命令,如果之前执行过,那么在hash中会有所记录,下次执行时,就会直接读取hash执行到系统tox,而不会根据PATH重新搜索到virtualenv环境中安装的tox。
# 此外,使用man hash还可以看到系统的内置命令
六、关于virtualenv:
基于微服务背景下的多服务部署,涉及很多内在的问题,比如各个服务之间的部署环境隔离、使用不同的版本等等。针对具体情况可能涉及:docker部署隔离(使用最多)、代码打包成不同RPM部署到不同目录下、virtual虚环境部署、mock环境隔离等。从使用来讲,virtualenv是非常简单,构建迅速,并且部署简单。
但是仍会有很多缺点,如果对virtualenv感兴趣的话,可以读一下这篇文章:
https://pythonrants.wordpress.com/2013/12/06/
其中存在的一些有趣的观点:
(1)virtualenv只提供python层面的隔离,如果软件包依赖了系统层级的东西,这种隔离是不可重入的;
(2)有更多的系统级别的隔离方案可选:比如虚拟机、LXC(容器)技术;
(3)virtualenv的部署是反模式的,只是更新了PYTHONPATH的路径,并没有对系统的完全控制权;
(4)pip和virtualenv只能从源码进行构建
(5)混乱的hack:在具体的虚环境下运行时需要硬编码,并且很难在虚环*调试;
(6)pip freeze的滥用:pip freeze会给出当前所有python软件列表,但该列表过于冗余和复杂。如果你想得到一个干净的运行依赖,你必须重新构建应用、寻找依赖,但很耗时。
七、其它:
(1)pip和virtualenv的作者是Lan Bicking,感兴趣的可以了解下:
下一篇: Mac终端美化