文章灵感来自于YouTube博主@程序员老王的python科普,可以看作是自己的学习笔记,你可以观看以下视频直接了解。
传统项目管理之难–环境与依赖
在我们写python代码时,我们必然会需要添加许多包,如果我没有安装对应的包,而直接在代码里写import package,那么运行就会报错。
为了解决这个问题,我们一般会在命令行当中输入下面的指令来安装对应的包:
pip install package
这样我们的import就没有问题了。但是这种方式带来了两个棘手的问题:
- 一个是安装在全局环境时无法满足不同项目对package版本的需求
- 另一个是无法处理好直接依赖与间接依赖的管理
环境依赖
我们先从环境问题开始。当我们执行pip install package时,默认安装路径是全局环境,这意味着所有项目可能都要调用这同一个package。但是往往不同的项目需要的依赖是不同版本的,这会导致有些项目产生版本冲突,运行会崩溃。
为了解决这个问题,python提供了一种虚拟环境的解决方案,我们可以在命令行运行以下指令:
pip -m venv .venv
它会在项目文件夹下新建一个.venv文件夹,pip会将这个项目所需要的全部依赖都安装到这个文件夹中;此外,pip还会修改每个package的sys.path属性,将.venv路径添加进去。
这样,当运行项目时,python会自动地在.venv文件夹下面寻找所需要的包,每个项目都是相互独立的,有着各自对应版本的包,就不会产生版本冲突问题。
Note: 如果你想要更详细的知道修改sys.path的原理的话,可以在运行以下python代码:
import sys,pprint
pprint.pp(sys.path)
你应该能够看到输出是几条系统路径,他其实就代表着python在寻找包时的检索路径
Info: 这个路径其实就像我们打开命令行时,会有几条指令不管在哪都可以运行,比如ls,rm,mkdir等等,这是因为这些系统会设定好一些默认的检索文件夹,当我们输入指令时,系统就会在这些文件夹去寻找对应的可执行文件。
在windows中的一个例子是:C:/windows/system32,在Linux中的一个例子是/usr/bin
环境依赖的管理
在环境问题解决后,我们可以安全地在当前项目安装所需依赖。
那如果其他人拿到项目,需要一个一个手动的去找齐依赖,岂不是太麻烦了?
这时候,我们可以用以下命令来将所需依赖打印出来:
pip freeze
在output中就可以看到所有的package了。一般来说,我们会通过重定向将所有信息存储到文件中:
pip freeze > requirements.txt
但这里就出现了我们说的第二个问题:直接依赖和间接依赖的管理。
requirements.txt中包含了项目所需的所有直接依赖和间接依赖,但是当我们把其中某个直接依赖删除时,它对应的间接依赖并不会随着一起删除,而是依然留在requirements.txt文件中,最终变成孤儿依赖,非常影响开发时的效率。
Python的官方标准
为了解决以上的难题,Python官方提出了一种pyproject.toml文件来同意管理包的依赖问题。
我们只需要在这个文件当中添加dependencies=["PackagesName"],并在里面输入所有需要的直接依赖的包名称即可。并且删除时也只需要将直接依赖项删除而不会受到间接依赖的干扰了。
Info: 这个过程依然只是删除了直接依赖而没有删除间接依赖,只是在配置文件中只显示直接依赖。这不会影响程序的运行。如果想要将间接依赖全部删除,需要将虚拟环境全部卸载再重新安装。
当拿到项目时,我们可以通过pip install .来在项目目录下完成,pip便会为我们打包好软件并安装对应依赖
此外还有一个问题便是当我们运行pip install .时,pip为我们打包的python文件夹中会包含两份一模一样的代码,而且不能动态更新。但这个问题可以通过加上-e参数来解决。它会生成一个动态链接,确保代码是实时更新的
社区的高效新工具
简单总结一下,我们用venv解决了环境依赖问题,用pyproject.toml来管理环境中的依赖。但是这样手动的一步步设置太繁琐了,有没有什么工具能够简化流程呢?
这其实就是最近社区流行的包管理器uv, poetry等的工作原理:将这些操作全部封装起来,并为用户提供一个更简易的接口。
这些工具在底层其实依然前面那一套,不过他的自动化管理更加智能一些。我们以uv为例。
假如我们项目上除了源码还有一个pyproject.toml文件,如果我们想要添加依赖,可以直接运行uv add packaga,这个过程uv会直接帮助我们创建好虚拟环境.venv,并且会在配置文件中自动添加对应的依赖,并激活对应的虚拟环境。
或者我们可以通过在新项目目录下运行uv venv && source .venv/bin/activate来创建并激活虚拟环境。它会自动为我们生成pyproject.toml文件。
当我们需要需要安装对应依赖时,也只需要输入:
uv sync
就可以自动将所有的包下来过来。
uv还可以通过uv run main.py的命令,自动在虚拟环境中运行代码,并且在结束时推出虚拟环境。
可以看出,uv本质其实就是将之前三四步的命令包装简化为一条命令,让开发者能够更专注于开发,拜托繁琐的依赖管理。而这些新工具,也是未来python项目管理的趋势。
当然,uv对我来说最大的好处,当然就是安装速度极快了😀。
Leave a comment