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
选项只在virtualenv
1.x 和 2.x 版本中有效。- 从
virtualenv
20.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/
后,执行python
pip
命令都会报错: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.*
,它们不是可执行文件),例如pip
tdqm
jupyter
,它们是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
# 退出虚拟环境
deactivate
venv
没有类似--relocatable
的功能,且生成的<虚拟环境名>/
文件夹也和virtualenv
生成的几乎一样,里面用到了<虚拟环境名>/
绝对路径 和 外部python解释器的绝对路径。
要想用venv
创建可移植的虚拟环境,要像virtualenv创建的虚拟环境一样,手动修改虚拟环境内文件。