欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python virtualenv

程序员文章站 2022-05-26 17:54:03
...

在使用virtualenv之前,可以先从这篇文章了解起来:

https://virtualenv-chinese-docs.readthedocs.io/en/latest/#


一、什么是virtualenv

virtualenv可创建隔离的Python开发环境,用于解决依赖、版本以及间接权限,它是workingenvvitrual-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 开头的脚本)时,使用的都是隔离环境下的模块。

(此外可更改setuptoolsdistribute的使用)

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

virtualenvwrappervirtualenv的扩展包,用于更加方便管理虚拟环境,包括:

(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-burritoautoenv

 

五、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)pipvirtualenv只能从源码进行构建

(5)混乱的hack:在具体的虚环境下运行时需要硬编码,并且很难在虚环*调试;

(6)pip freeze的滥用:pip freeze会给出当前所有python软件列表,但该列表过于冗余和复杂。如果你想得到一个干净的运行依赖,你必须重新构建应用、寻找依赖,但很耗时。

 

七、其它:

1pipvirtualenv的作者是Lan Bicking,感兴趣的可以了解下:

http://www.ianbicking.org/blog/