virtualenv教程
virtualenv 教程
参考资料:
安装
通过pip安装virtualenv:
pip install virtualenv测试你的安装
virtualenv --version创建环境
查看你机子上不同版本python的地址
which python
which python2
which python2.7
...会返回一个地址,是你需要的python所在<路径>,复制它。
若想安装的python版本,在本地没有,可以用conda创建一个环境安装这个python:
conda create -n <conda环境名> python=x.x.x创建虚拟环境
创建方法
可在任意选定<目录>创建虚拟环境,会生成<目录>/<虚拟环境名>/,其中存放python包。
cd <目录>
virtualenv --python=<路径> <虚拟环境名>
pip install virtualenv若--python=<路径> 参数省略,则使用which virtualenv 所返回文件的shebang中的python路径,而非使用which python返回路径。
创建后,<目录>下会生成<虚拟环境的名字>文件夹,其下有bin/,include/,lib/
- <目录>可为用户根目录(即~/),用于创建整个用户的虚拟环境
- <目录>可为工程目录,用于创建本工程使用的虚拟环境
权限不足
The program 'virtualenv' is currently not installed. To run 'virtualenv' please ask your administrator to install the package 'python-virtualenv'请服务器管理员安装python-virtualenv
sudo pip install virtualenv或者用安装miniconda,然后用conda的pip安装virtualenv:
pip install virtualenv使用
安装python的包
装pip的软件,必须先到虚拟环境所在目录
cd <目录>输入一下命令激活python的虚拟环境
cd <目录>
source <虚拟环境名>/bin/activate激活成功后,用户名前会加(<目录>)
此时,输入以下命令装软件
pip install <软件>安装完成后,从虚拟环境出来
deactivate使用python及python的包
当<目录>为某pyhton工程文件夹:
只有在该工程目录,输入source <虚拟环境名>/bin/activate激活后,才能使用该virtualenv虚拟环境,包括python版本、pip、python包,一经激活在任意目录下均可使用。
可移植的环境
若虚拟环境所依赖的外部python删除/受损/移动、项目路径移动、环境文件夹重命名、或把项目/环境移动到另一台操作系统相似的机器,virtualenv所创建的虚拟环境将无法使用。
要解决这些问题,就需要创建可移植的虚拟环境,使得上述操作后,virtualenv虚拟环境还能正常使用,即:能运行python,能调用之前在虚拟环境中安装的python包,能使用pip装卸包。方法如下:
virtualenv --relocatable
命令virtualenv --relocatable <虚拟环境名>,创建可移植的虚拟环境。
- --relocatable选项只在- virtualenv1.x 和 2.x 版本中有效。
- 从 virtualenv20.x 版本开始,--relocatable选项被删除,因此无法在这些版本中使用,需要手动修改虚拟环境内文件,才能创建可移植的虚拟环境。
手动修改虚拟环境内文件
下面不妨取<目录>=venv。
内置python
有效方法:手动拷贝conda环境
在用conda的非base环境的python版本,创建virtualenv后,
conda create -n <conda环境名> python=x.x.x
conda activate <conda环境名>
virtualenv venv只要改好上面这几条,即使conda env remove --name <conda环境名>删除这个conda环境,仍能使用venv/虚拟环境。
- 
拷贝conda环境到env中: cp -r /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名> venv/conda-env
	venv/conda-env/中的 conda环境绝对路径/home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名>无需修改,即使删除这个conda环境,也不会影响使用venv/环境。
- 
venv/pyvenv.cfg中,改写成相对pyvenv.cfg的路径:把 home = /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名>/bin implementation = CPython version_info = 3.11.5.final.0 virtualenv = 20.28.0 include-system-site-packages = false base-prefix = /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名> base-exec-prefix = /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名> base-executable = /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名>/bin/python3.10改成 home = ./conda-env/bin implementation = CPython version_info = 3.10.15.final.0 virtualenv = 20.28.0 include-system-site-packages = false base-prefix =./conda-env base-exec-prefix =./conda-env base-executable = ./conda-env/bin/python3.10
- 
把 bin/python -> /home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名>/bin/python,改为指向venv/内的相对路径的链接:ln -sf ../conda-env/bin/python python
无效方法1: 拷贝python文件
只拷贝/gpfs-flash/junlab/haoyu/bridge-VC/code/venv/bin/python文件,去替代venv/bin/python链接。
这样无效,执行python获pip命令时,会有如下报错:
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Python path configuration:
  PYTHONHOME = (not set)
  PYTHONPATH = (not set)
  program name = 'python'
  isolated = 0
  environment = 1
  user site = 1
  import site = 1
  sys._base_executable = '/gpfs-flash/junlab/haoyu/bridge-VC/code/venv/bin/python'
  sys.base_prefix = '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC'
  sys.base_exec_prefix = '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC'
  sys.platlibdir = 'lib'
  sys.executable = '/gpfs-flash/junlab/haoyu/bridge-VC/code/venv/bin/python'
  sys.prefix = '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC'
  sys.exec_prefix = '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC'
  sys.path = [
    '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC/lib/python310.zip',
    '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC/lib/python3.10',
    '/home/haoyu/ENV/localENV/anaconda3/envs/bridge-VC/lib/lib-dynload',
  ]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'
Current thread 0x00007f7da2f9f4c0 (most recent call first):
  <no Python frame>这是因为,python代码的解释,需要使用conda下的一整个环境,单个python文件无法完成。
无效方法2:–always-copy参数
用virtualenv --always-copy venv创建虚拟环境
- 
使用 --always-copy参数,能把conda环境中的python{,3,3.10}拷贝到venv/bin/python{,3,3.10}。若无此参数,则是创建链接: venv/bin/python{3,3.10}->venv/bin/python->/home/haoyu/ENV/localENV/anaconda3/envs/<conda环境名>/bin/python
- 
但是,即便用了 --always-copy参数,一旦删除这个conda环境,就无法使用venv/虚拟环境:在激活venv/后,执行pythonpip命令都会报错:Could not find platform independent libraries <prefix> Could not find platform dependent libraries <exec_prefix> ...(同上文)其原因和[无效方法1: 拷贝python文件](#无效方法1: 拷贝python文件)相同。 
- 
使用 --always-copy参数,对以下行为没有影响:- venv/bin里的shebang是- venv/bin/python的绝对路径
- venv/bin/activate*里的VIRTUAL_ENV 是- venv/的绝对路径
- venv/pyvenv.cfg里是conda环境的绝对路径
 
内置lib
若当前venv环境还依赖于某些lib(比如libsndfile),不能用pip安装,只能用apt/conda/手动 安装,
sudo apt install libsndfile1
# 无需修改LD_LIBRARY_PATH,因为默认LD_LIBRARY_PATH=/opt/cudnn/lib64:/usr/local/cuda/lib6 中已经加载了 libsndfile1
# 或
conda install -c conda-forge libsndfile
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CONDA_PREFIX/lib
# 或从 https://packages.debian.org/zh-cn/sid/libsndfile1 手动下载,然后修改LD_LIBRARY_PATH以加载之要想把它内置到venv/里,需要创建venv/lib/libsndfile/,将这些lib文件拷贝到其下。
然后在venv/bin/activate中添加下面一行,使得激活venv环境时,就完成修改LD_LIBRARY_PATH,以调用这些lib文件。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$VIRTUAL_ENV/lib/libsndfile如此,即便 apt/conda/手动 卸载了libsndfile,在venv中也还能使用libsndfile。
使用相对路径
若跟进一步,还希望项目<目录> 或 <venv>重命名或移动(包括跨机器移动、但必须两台机器的操作系统相似)后,还能使用venv/虚拟环境。则在前述内置python和内置lib之外,还需要做如下修改:
- 
修改 venv/bin/acitvate*中变量VIRTUAL_ENV(或``virtual_env`)的定义:- 
activate.{csh,fish,nu}:用的是venv/的绝对路径,当前shell不是csh/fish/nu的话,就不用改
- 
activate_this.py和activate.ps1: 原本就用相对当前文件的路径,不需要修改
- 
activate:需要改,见下:从 VIRTUAL_ENV=/home/haoyu/project/venv改为 # get absoltae path to the dir this is in, work in bash, zsh # if you want transfer symbolic link to true path, just change `pwd` to `pwd -P` VIRTUAL_ENV=$(cd "$(dirname "${BASH_SOURCE[0]-$0}")/.."; pwd)
 
- 
- 
修改shebang: 把 venv/bin/下有许多可执行文件(不是activate.*,它们不是可执行文件),例如piptdqmjupyter,它们是python脚本,但没有.py扩展名,用来调用相应的python包。这些文件的第一行是shebang: #!/absolute/path/to/venv/bin/python,表示强制用这个python执行当前可执行文件。需要将其换成 #!/usr/bin/env python,表示强制用which python执行当可执行前文件。批量替换命令,如下: find venv/bin/ -type f | xargs -I{} sed -i -E '1s|^#!/.+/python$|#!/usr/bin/env python|' {} rg -uu '#!' venv/bin/若不这样修改,当venv的路径移动后,调用这些python包时会出现如下bug: Could not find platform independent libraries <prefix> Could not find platform dependent libraries <exec_prefix> ...(同上文)注:在venv环境内,每当pip安装新的包后, venv/bin/中会自动添加新的python脚本,去调用相应的python包,记得执行上面的批量替换命令,以修改它们的shebang,才能在移动venv后还能使用虚拟环境。
venv命令
python3.3以后的版本中包含venv模块(不需要用户安装其他任何包),其功能和 virtualenv 一样,能在当前目录创建<虚拟环境名>/文件夹,存放python包。
命令如下:
# 创建虚拟环境
python -m venv <虚拟环境名>
# 进入虚拟环境
source <虚拟环境名>/bin/activate
# 退出虚拟环境
deactivatevenv没有类似--relocatable的功能,且生成的<虚拟环境名>/文件夹也和virtualenv生成的几乎一样,里面用到了<虚拟环境名>/绝对路径 和 外部python解释器的绝对路径。
要想用venv创建可移植的虚拟环境,要像virtualenv创建的虚拟环境一样,手动修改虚拟环境内文件。