Python虚拟环境与包管理工具(uv、Conda)
文章目录
- 简介
- 为什么需要虚拟环境(虚拟环境解决什么问题)
- 从PyCharm的Interpreter看虚拟环境工具
- 从Python的venv理解虚拟环境
- 如何将环境的依赖分享给其他人
- 更便捷的工具uv
- uv安装
- uv配置
- uv Python版本管理命令
- uv项目管理命令
- uv创建虚拟环境
- Conda家族
简介
之前一直是Python的轻度用户,主要使用Jupyter Notebook,所以安装包基本使用pip来安装。
偶尔一点小项目使用PyCharm的interpreter也没有太关心包的依赖问题。
但是最近做AI项目,有一些复杂的依赖,总感觉有些模糊,于是重新梳理了Python虚拟环境、包管理与包管理工具。
现在分享给大家,希望能够帮助到你。
为什么需要虚拟环境(虚拟环境解决什么问题)
首先来解释一下为什么Python需要一个虚拟环境。
因为一些大型的项目都会有大量的外部第三方依赖,而这些第三方依赖又可能会依赖其他第三方的包。
当项目比较大的时候,整个项目的依赖树就会变得非常复杂。
Python最早的目标就是一个便捷的脚本语言,从“人生苦短,我用Python”的口号也能看出来,目标就是为了方便,快速实现功能。
现在来看Python显然达到了它的目标,但Python的设计者显然没有想到Python的方便会催生出一个如此繁荣的生态。
所以,开始压根就没有仔细设计过包管理这个事情,所有库往Lib下一扔完事,哦,还有三方库啊,那往Lib下的site-packages一扔完事。
如果,不清楚Python怎样找依赖包,可以参考:Python包模块与模块导入查找顺序
现在问题来了,加上项目ProjectA依赖numpy 1.13版本,ProjectB依赖2.3版本,怎么办呢?(site-packages只能安装一个版本的numpy,不像Java的maven,不同的包自带版本号,lib中可以有不同的版本,根据版本号区分就可以)
好办,将ProjectA的1.13版本升级为2.3版本,不就完了么?
啥?有不兼容代码,改一下不就完了,多大点事啊。
但是当你有100个项目呢?这其中有些项目的numpy版本不能改,因为还涉及依赖的第三方包依赖numpy,我们没有办法修改第三方包的代码。
啥?换第三方依赖包的版本?
这就没完没了,特别是项目特别多的时候,基本不可能完全兼容,处理一个项目的依赖兼容问题就已经让人头秃了,处理100个甚至更多项目的兼容问题,要死人的!
怎么办呢?
为每个Python项目复制一个Python环境不就完了,这样每个项目都有自己的site-packages,不和其他公用依赖项目,依赖冲突解决起来就容易多了。
复制Python环境,外加一堆配置,就相当于一个虚拟环境。
但是每次新建项目都去复制Python环境,处理配置,好麻烦,怎么办呢?
于是,聪明勤劳的开发者就动手开发出了一堆工具。
没错,因为开始没有官方标准,所以开发者们创造出了一堆工具。
当然官方也意思到这个问题,于是3.3版本开始官方推出了一个venv模块,v是Virtual的首字母,env是Environment的简写,可以参考:虚拟环境和包
从PyCharm的Interpreter看虚拟环境工具
现在常用的虚拟环境工具有:
- Python自带的模块venv
- Conda家族
- Virtualenv
- Poetry
- Pipenv
- uv
Conda家族这里不多介绍,,想要知道什么是Conda、什么是Anaconda distribution、什么是Miniconda、什么是forge-conda、请参考后文。
Python的venv模块后面介绍,方便我们理解流程以及为什么需要uv这类包管理工具。
其他的可以参考下面的命令简单看一下:
# 安装virtualenv
pip install virtualenv
# 使用virtualenv创建虚拟环境
virtualenv myenv# 安装pipenv,使用清华的源
pip install pipenv -i https://pypi.tuna.tsinghua.edu.cn/simple# 创建虚拟环境
pipenv install `--python 3.8`
# 更多pipenv的用法可以使用-h来查看
# 激活虚拟环境
pipenv shell
pipenv -h
从Python的venv理解虚拟环境
我们先创建一个简单的工程,就只有一个文件,使用了numpy:
import numpy as np# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr)# 创建一个二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组:\n", arr2d)# 数组加法
sum_arr = arr + 10
print("数组加法:", sum_arr)# 计算均值
mean_val = np.mean(arr)
print("均值:", mean_val)
非常简单,就是一个简单的numpy示例程序,我们没有numpy,按照我们最开始的习惯使用pip安装numpy
pip install numpy
安装成功,执行没有问题
但是我们可以通过命令查看numpy安装的位置:
pip show numpy
我们可以看到numpy默认的安装位置是在E:\language\python\313i\Lib\site-packages这个全局库中,显然,这不合适,很容易导致和其他项目依赖冲突。
如何解决这个问题呢?
我们可以使用Python3.3开始的venv模块。
# Python自带venv创建虚拟环境
python -m venv myenv
执行命令之后,我们可以看到venv在项目的目录下创建了一个myenv的文件,下面就包含了Lib/site-packages和Scripts目录。
是不是和PyCharm创建项目比较像了,如果我们的名字是.venv是不是就更像了,通常我们会使用.venv这个名字,因为很多工具会自动处理,如果是myenv这种,如果导入到PyCharm中,它识别不了。
我们可以看到Scripts目录下有一个activate.bat脚本,这个就是用来激活环境的脚本。
# Windows-激活环境
myenv\Scripts\activate
# Linux-激活环境
source myenv/bin/activate
激活之后,我们可以看到命令行前面会有虚拟环境名字:
然后,我们重新在激活环境下安装numpy就会安装在项目的Lib/site-packages中。
为什么会怎样呢?其实就是修改了sys.path,我们可以通过下面的脚本来看虚拟环境和非虚拟环境的区别:
import sys,pprintpprint.pp(sys.path)
虚拟环境:
非虚拟环境:
还不理解,那你肯定没看前面我们说的Python包模块与模块导入查找顺序
如何将环境的依赖分享给其他人
问题又来了,我们自己创建了一个虚拟环境,进行开发,安装了依赖,但是其他人怎么知道我安装了哪些依赖呢?
比较原始的做法是使用pip freeze,这个命令的作用是打印虚拟环境中安装的所有包及其确切的版本号。
我们可以通过pip freeze命令将结果重定向到一个文件中分享给其他人,这个文件名字通常叫做requirements.txt,这样其他人就可以通过查看这个文件,知道我们引入了哪些依赖。
其他人,也可以用过pip install -r requirements.txt安装指定的依赖。
pip freeze >> requirements.txtpip install -r requirements.txt
现在,问题又来了:
pip freeze有一个问题就是它不区分直接依赖和间接依赖,例如我先安装了一个pandas包,会引入一堆依赖,后来我们不需要pandas了,我们使用pip uninstall pandas之后,它只会卸载掉pandas,而不会卸载掉安装pandas安装的间接依赖。
在JAVA的maven中我们可以使用pom.xml来定义这个项目依赖的包及其版本。
Python现在也有类似的机制了,可以创建一个pyproject.toml文件来配置依赖的包及其版本。
[project]
name = "learn-env"
version = "0.1.0"
dependencies = ["numpy>=2.3.2",
]
然后我们可以使用命令来安装依赖:
# 把当前项目安装到虚拟环境中
pip install .# 加上-e参数,这样避免把源代码也复制到site-packages目录了
pip install -e .
小结一下:
- 创建虚拟环境:python -m venv myenv
- 激活环境:myenv/bin/activate
- 编辑pyproject.toml文件,添加直接依赖
- 安装依赖:pip install -e ·
感觉还是有些麻烦,有没有更便捷一点的方法呢?
答案当然是有,Python就这点好,总有社区的朋友们创造各种各样的工具让事情更方便,比较人生苦短嘛。
更便捷的工具uv
uv能干什么呢?
- Python安装
- 虚拟环境
- 依赖管理
- 工具安装
- 打包发布
uv安装
首先去官网或者GitHub看看。
uv官方网站
uv doc
uv GitHub
然后根据提示安装uv:
# <!-- 以管理员的身份运行 -->
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"# 如果实在不行就使用
pip install uv
uv配置
uv配置文件
简单总结,用户级配置:
- Windows: %APPDATA%\uv\uv.toml
- Linux: ~/.config/uv/uv.toml
主要配置源:
index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"
可以用命令临时切换:
set UV_DEFAULT_INDEX=https://mirrors.aliyun.com/pypi/simple/
或者使用环境变量UV_PYPY_INSTALL_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
uv具体配置项
uv环境变量说明
- UV_CACHE_DIR:缓存目录
- UV_PYTHON_BIN_DIR:Python可执行文件安装目录
- UV_PYTHON_INSTALL_DIR:Python安装存储目录
- UV_TOOL_DIR:工具安装目录
- UV_PYTHON_INSTALL_MIRROR:Python下载镜像
- UV_PYPY_INSTALL_MIRROR:设置pypi源
- UV_DEFAULT_INDEX:默认的查找包源
怎么使用呢?
uv默认下载Python会去github库下载:uv-python-release
我们很多时候连不是GitHub,要么连上了也比较慢,这个又没有镜像可以用,怎么办呢?
可以先利用:github代理下载这类代理下载到本地。
然后配置环境变量使用本地目录:
export UV_PYTHON_INSTALL_MIRROR=file:///home/tim/uv_python_install_mirror
UV_PYTHON_INSTALL_MIRROR
file://D:/appdata/python/uv-mirror
注意本地文件使用的是file://开头,另外有日期的子目录,文件名也一定要对应上
注意:默认安装目录
uv Python版本管理命令
# 查看本地安装的Python
uv python list# 查找指定的版本
uv python find 3.13uv python install cpython-3.14.0rc2-windows-x86_64-none
uv项目管理命令
# 初始化一个项目
uv init
# 添加项目依赖
uv add pandas# 添加开发依赖
uv add --dev pytest# 运行文件
uv run python main.py
uv run main.py
# 指定Python版本,慎用,会删除所有依赖,重新创建虚拟环境
uv run -p 3.14 main.py# 移除项目依赖
uv remove pandas# 根据配置文件下载安装依赖
uv syn# 项目依赖分析
uv tree# 项目打包
uv build# 项目发布
uv publish# 自我升级
uv self update
uv生成的文件说明:
uv add命令做了啥
使用uv run命令运行文件:
使用uv tree分析项目依赖:
uv创建虚拟环境
uv除了使用add被动创建虚拟环境,还可以使用venv竹筒创建,可以使用–python参数指定Python版本。
# 在当前目录创建虚拟环境默认名称:.venv
uv venv# 指定 Python 版本 (uv 会尝试寻找已安装的匹配版本)
uv venv --python 3.11# 指定环境名称
uv venv my-env
Conda家族
Conda本身用起来很方便,但是Conda家族之间的关系比较复杂,主要涉及有商业许可的问题。
下面就简单的来介绍一下:
- Conda
- Miniconda
- Anaconda distribution
- conda-forge
- Miniforge
- Mamba
首先Conda是一个商业公司开发的包管理工具,不仅仅是管理Python,也支持R、Go等。
这个公司最早搞了Anaconda distribution就是为了解决Python包的管理和依赖问题,他们自己维护了一个包库,是他们解决了各种依赖问题之后的包,特别是一些C写的包的依赖问题。
结果因为Python早期的糟糕的包管理问题,很多做数据科学的都开始用Anaconda distribution,因为的确方便,不用去处理依赖,用的人越来越多,火了。
所有,后来公司名字干脆都改成了Anaconda。
因为Anaconda distribution预安装了很多包,太重了,后来用的人多了,很多不需要那么多包,所有他们搞了一个Miniconda。
收费又是怎么一回事呢?
Conda本身是开源的,不收费,收费的是Channel,就是Anaconda公司自己精心维护的那个库,并且是200人以上的公司,个人和学校还是可以免费用。
老实说,Anaconda公司这还是很良心,人家花精力处理依赖还要维护,要服务器,对于200人以上公司收费也合理。
毕竟200人以上的公司也不小了,一直白嫖人家的资源,人家收费也无可厚非。
如果,的确不想被商业许可困扰,也有社区方案Miniforge登场,同样是Conda,但是默认的Channel conda-forge是社区维护的,虽然质量可能没有Anaconda distribution高,但是丰富,并且免费啊。
至于Mamba就是,使用C语言实现了Conda的功能,相当于给Conda提速了。
至于Conda的用法,这里就不过多的介绍了,因为懂的不需要介绍,不懂的我推荐你用Python新的包管理工具uv,方便并且发展迅速。
Miniconda Anaconda distribution下载
miniforge下载-官网
miniforge下载-GitHub
miniforge下载-清华镜像